Authentication

API key format, four ways to authenticate, key management, balance and billing

API key format#

An API key (shown in the console as a "sub-key") looks like:

sk-gpushare-{64 hex characters}

Example: sk-gpushare-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef

Total length is 76 characters (the 12-character sk-gpushare- prefix plus 64 hex characters). Configure key-validation and secret-scanning regexes against that length.

The raw key is stored server-side encrypted with AES-256-GCM and can be revealed again at any time on its detail page in the console. Only a handful of early hash-only keys can't be revealed — if you lose one of those, create a new key.

The same key works on every public endpoint: all four chat protocol endpoints, the image / video / music APIs and the knowledge base API & MCP.

Creating and managing keys#

Go to oem.dflop.top/dashboard/keys:

  1. Create Key — a name (required), an optional allowed_models allowlist, and an optional expiry
  2. View any time — the detail page can reveal the raw key (stored encrypted server-side)
  3. Check usage — per-request history with model, tokens and cost
  4. Revoke — any key can be disabled or deleted immediately

What you can configure per key#

FieldMeaningDefault
nameHuman-readable name, for auditingrequired
allowed_modelsModel allowlist. NULL or omitted means every model is allowed. ⚠️ Do not pass an empty array — an empty array denies every model and each request returns 400 model_not_allowedomitted (all allowed)
expires_atExpiry timenone
enabledEnabled / disabledtrue

There is no budget setting on a key. Budget lives in the account balance, shared by every key — see Balance and billing below. The only per-key controls are allowed_models, expires_at and enabled; they exist for access control and auditing, not budget isolation.

Four ways to authenticate#

The gateway looks for a key in this order and stops at the first hit — any one of them works:

x-api-keyx-goog-api-key?key=Authorization: Bearer

If you don't know which to pick, use Authorization: Bearer. It's the one form that works on every endpoint and with every SDK (point the OpenAI, Anthropic or Gemini SDK's base_url here and all three accept it), and it's what every example in these docs uses. The other three exist so that an SDK which already sends its own header needs no changes — they are fully supported, not second-class.

1. x-api-key header#

curl https://oemoemapi.dflop.top/v1/messages \
  -H "x-api-key: sk-gpushare-xxx" \
  ...

The Anthropic SDK and Claude Code use this by default. It's the most direct, and the least likely to be swallowed by an intermediary.

2. x-goog-api-key header#

curl https://oemoemapi.dflop.top/v1beta/models/gemini-2.5-flash:generateContent \
  -H "x-goog-api-key: sk-gpushare-xxx" \
  ...

The default header of Google's genai SDK — Gemini SDK users need no changes at all. The value never lands in a URL access log, so there's no leakage risk.

3. ?key= query parameter#

curl "https://oemoemapi.dflop.top/v1beta/models/gemini-2.5-flash:generateContent?key=sk-gpushare-xxx" \
  ...

The Gemini REST-style alternative. Not recommended by hand — the key ends up in access logs and browser history.

4. Authorization: Bearer header#

curl https://oemoemapi.dflop.top/v1/chat/completions \
  -H "Authorization: Bearer sk-gpushare-xxx" \
  ...

The OpenAI SDK uses this by default.

Exception: GET /v1/models accepts only the Authorization: Bearer and x-api-key headers — ?key= is not supported there.

What we recommend#

ClientRecommended method
Unsure / new integrationAuthorization: Bearer — the universal form, accepted everywhere
OpenAI SDKAuthorization: Bearer (SDK default, nothing to change)
Anthropic SDKx-api-key (SDK default, nothing to change)
Google Gemini SDKx-goog-api-key (SDK default, nothing to change)
curl / by handAuthorization: Bearer
Server-side codeenv var → Authorization: Bearer

Use an env var, never a hardcoded key#

# ~/.bashrc
export PLATFORM_API_KEY=sk-gpushare-xxx
client = OpenAI(
    api_key=os.environ["PLATFORM_API_KEY"],
    base_url="https://oemoemapi.dflop.top/v1",
)

Balance and billing (one wallet)#

The platform is prepaid, not post-pay.

The billing model#

Budget lives in your account balance (a USD wallet) and every API key draws on that same balance. A key has no budget pool of its own — it's an access credential.

  • Trial credit: 121.32 on sign-up, enough to run every getting-started example
  • Top up: dflop.top/dashboard/billing (Stripe, 404.4 minimum; same SSO account as oem.dflop.top, shared balance)
  • Check it: the console dashboard shows your balance and per-key usage in real time

Billing units depend on the endpoint:

EndpointBilled by
chat / embeddingstokens (actual usage × unit price; when the upstream returns cached_tokens the cached rate applies automatically, nothing to switch on)
imagesper image (unit price × count — see Media APIs)
videoper second (settled on the actual generated duration, refunded in full on failure)

Each chat request goes through two steps:

  1. Pre-charge — estimate the worst-case cost and compare it to your balance. Over budget returns 402 and nothing is sent upstream.
  2. Settle — after the turn, deduct the real token usage from the balance and write a usage log entry.

How pre-charge estimates#

Pre-charge is deliberately worst-case:

  • Input ≈ the messages JSON byte length ÷ 4
  • Output counts your explicit max_tokens in full. Without max_tokens it estimates min(the model's default_max_tokens, 32768). The model's real output ceiling can be far higher — 128K for gpt-5.x and Claude Opus/Sonnet 5, 131072 for GLM and Grok, 256K for Kimi — and when you omit the parameter the gateway raises the on-wire max_tokens to that ceiling for you. The estimate deliberately doesn't assume the ceiling, so a low balance isn't rejected for no reason.

If the estimate exceeds your balance you get a 402 even when the real usage would have been far smaller. When your balance is tight, pass a smaller explicit max_tokens to get through pre-charge. Note also that settle does not gate again, so under concurrent requests the balance can dip slightly negative (the next request is then rejected).

Out of balance#

Returns HTTP 402 Payment Required. OpenAI shape (/v1/chat/completions and friends):

{"error": {"message": "Insufficient balance. Please top up and try again.", "type": "insufficient_quota", "code": "quota_exceeded"}}
  • When the balance is ≤ 0 you get the 402 during authentication, before pre-charge even runs
  • /v1/messages returns the Anthropic shape (type: "billing_error", no code field) and /v1beta returns the Gemini shape (status: "RESOURCE_EXHAUSTED"). Side-by-side comparison: Error handling

Fix: top up at dflop.top/dashboard/billing. Creating a new key does not help — every key shares one balance, so when it runs out they all 402 together.

Working with several keys#

A key is a credential, not a budget pool, so multiple keys are about access isolation and attribution:

SituationSuggested key setup
Personal development / experimentingone key with no model restriction
Production serviceallowed_models locked to 1–2 models, named distinctly for auditing
One-off calls / spikesa short-lived key with expires_at, revoked when done
Team useone key per person, named after the user (note: they share one balance)

Security advice#

  1. Never commit a key to git, put it in a screenshot, or paste it into Slack
  2. Inject it as an env var with direnv, the 1Password CLI or Doppler
  3. Revoke immediately in the console if you suspect a leak
  4. Keep keys in server-side code — calling from the browser exposes them
  5. If a browser must call the API, proxy through your backend
  6. Because a key can be revealed in the console at any time, the security of the console account itself matters just as much — protect the SSO account

CSRF / Origin#

Gateway endpoints do not enforce Origin or CSRF tokens — authentication is the key alone. A leaked key therefore means full exposure.

(The oem.dflop.top console itself uses cookies plus a CSRF token, but that's separate admin-panel auth and doesn't affect the gateway API.)