Authentication

JoyToken’s OpenAI-compatible API uses API key authentication. The model invocation entry point is POST /openai/v1/chat/completions. The gateway validates the key before policy checks, routing, wallet freeze, provider invocation, usage recording, and billing attribution.

API keys represent real wallet credits and policy permissions. Do not put plaintext keys in browsers, mobile bundles, public repositories, logs, or issue screenshots. Production requests should originate from your server.

Use an API Key

New integrations should use Authorization: Bearer:

cURL
$curl https://api-dev.joytokens.ai/openai/v1/chat/completions \
> -H "Authorization: Bearer $JOY_TOKEN_API_KEY" \
> -H "Content-Type: application/json" \
> -H "X-Request-ID: auth-example-001" \
> -d '{
> "model": "auto",
> "tier": "standard",
> "messages": [
> { "role": "user", "content": "ping" }
> ],
> "stream": false
> }'

If you already use the OpenAI SDK, only replace apiKey and baseURL:

1import OpenAI from "openai";
2
3const client = new OpenAI({
4 apiKey: process.env.JOY_TOKEN_API_KEY,
5 baseURL: "https://api-dev.joytokens.ai/openai/v1",
6});
7
8const response = await client.chat.completions.create({
9 model: "auto",
10 messages: [{ role: "user", content: "Say hello from JoyToken." }],
11});
12
13console.log(response.choices[0]?.message?.content);

Headers

HeaderRequiredCurrent behavior
AuthorizationYesRecommended format: Bearer $JOY_TOKEN_API_KEY
X-API-KeyOptionalCompatibility format. If both headers exist, the gateway reads X-API-Key first
Content-TypeYesJSON requests use application/json
X-Request-IDOptionalUsed for gateway logs, provider calls, billing records, and troubleshooting; when missing, the gateway generates req-*

X-API-Key is a compatibility path, not the preferred default for new projects. Standardizing on Bearer tokens reduces special handling in proxies and SDKs.

Gateway Validation Flow

api-gateway extracts the plaintext key from request headers and validates it through apikey-service ValidateApiKey. Only after validation does the gateway build policy, call the router, and invoke the provider.

Client
-> api-gateway
-> apikey-service ValidateApiKey
-> policy check
-> wallet precheck / freeze
-> router-service
-> provider-adapter-service
-> upstream model

The validation result is used for routing and billing:

FieldUsed for
valid / statusDetermines whether the key can be used. Current gateway requires valid = true and status = ACTIVE
api_key_idUsage records, billing attribution, wallet quota sync
owner_id / tenant_idPersonal or organization ownership
billing_type / billing_idSelects personal wallet or organization account
tierAPI key tier constraint
fixed_modelRestricts the key to a single model
limit_total / limit_daily / limit_weeklyInputs for quota checks
policy_snapshot_jsonPolicy snapshot bound when the key was created, including IP rules, model blacklist, routing strategy, and tiers

Policy and Wallet Checks

Successful authentication does not guarantee execution. The gateway continues checking:

CheckCommon failure response
Body parsing, non-empty messages, and 8 MiB body limit400 invalid_request_error
Key active status403 invalid_api_key
IP allowlist/blocklist, model blacklist, fixed model, and tier policy403 policy_rejected
Wallet balance, budget, and freeze amount402 insufficient_quota
Router service or provider invocation failure502 routing_error or upstream_error

Error responses keep the OpenAI-compatible shape:

Error response
1{
2 "error": {
3 "type": "missing_api_key",
4 "message": "missing api key"
5 }
6}

Governance Signals

Successful responses preserve OpenAI-compatible choices and usage. JoyToken adds headers and metadata:

SignalLocationMeaning
X-DAOE-Used-Modelresponse headerActual model used
X-DAOE-Used-Providerresponse headerActual provider used
X-DAOE-Failoverresponse header1 when streaming provider failover happened
metadata.modelresponse body / stream metadataFinal model
metadata.tierresponse body / stream metadataRouting and billing tier
metadata.scoreresponse body / stream metadataRouter score for the selected model
metadata.billingresponse body / stream metadataCredits, input/output tokens, cache tokens
metadata.latencyresponse body / stream metadatarouting_ms, first_token_ms, stream_ms

Non-streaming responses merge metadata into the JSON body. Streaming responses append a metadata event before [DONE]:

Streaming tail
data: {"metadata":{"model":"GLM-5","tier":"standard","billing":{"credits_used":"0.2288","input_tokens":24,"output_tokens":14}}}
data: [DONE]

Server-Side Proxy

Browsers and mobile clients should not hold JoyToken API keys. Send requests to your backend and inject the key there:

Browser -> Your backend -> JoyToken /openai/v1/chat/completions
Next.js route handler
1export async function POST(req: Request) {
2 const body = await req.json();
3
4 const response = await fetch("https://api-dev.joytokens.ai/openai/v1/chat/completions", {
5 method: "POST",
6 headers: {
7 "Content-Type": "application/json",
8 Authorization: `Bearer ${process.env.JOY_TOKEN_API_KEY}`,
9 "X-Request-ID": crypto.randomUUID(),
10 },
11 body: JSON.stringify(body),
12 });
13
14 return new Response(response.body, {
15 status: response.status,
16 headers: response.headers,
17 });
18}

In production, do not let clients submit arbitrary apiKey values. If you need multi-tenant billing, choose the JoyToken key on your server based on user, team, or project.

Rotate API Keys

  1. Create a new key with the same or stricter policy.
  2. Write the new key to your server-side secret manager or environment variables.
  3. Send a validation request with a new X-Request-ID.
  4. Confirm that the new key has traffic in JoyToken Logs / Usage.
  5. Disable or revoke the old key.
  6. Check for old-key failure logs during the transition window.

Security Guidance

  • Use a separate key per application, environment, and agent workflow.
  • Bind production keys to budget, tier, model policy, and IP allowlists when needed.
  • Do not put keys in frontend .env, browser localStorage, mobile bundles, or logs.
  • Send X-Request-ID for high-risk agent calls, including workflow ID and step ID.
  • If a key leaks, revoke it, create a new key, and inspect Usage and Billing.