Key format
Every ByteSpike key starts withsk-byts-. You generate them in
Console → API keys; the
secret value is shown once at creation time, then masked. To
retrieve a plaintext later, use the per-key reveal flow in the console
or GET /v1/keys/{id}/reveal on the management API.
Header layout per protocol
ByteSpike accepts the native auth header for whichever protocol you’re calling. The same key works across all three — pick the header your client speaks.| Protocol | Header | Example |
|---|---|---|
| Anthropic Messages | x-api-key | x-api-key: sk-byts-... |
| OpenAI Chat Completions / Responses | Authorization: Bearer | Authorization: Bearer sk-byts-... |
| Gemini Native | query param ?key= | ?key=sk-byts-... |
Authorization: Bearer on the Anthropic endpoint
and x-api-key on the OpenAI endpoint — the gateway accepts both
shapes on both routes. If both headers are present, x-api-key wins.
The gateway never reads request bodies to discover credentials.
Per-key controls
Each key carries its own configuration, set when you create the key and editable later from the console:| Field | What it does | Default |
|---|---|---|
name | Display label in the console — pick something memorable like prod-vision-pipeline | required |
group_id | Which routing group this key can hit. Picking claude-default means the key can only call Claude models; default routes every model. See Models. | required (single value per key) |
quota | Hard cap on lifetime spend in USD. 0 = unlimited. | 0 |
expires_in_days | Auto-revoke after N days. | never |
rate_limit_5h | USD cap on the rolling 5-hour window. 0 = unlimited. | 0 |
rate_limit_1d | USD cap on the rolling 24-hour window. | 0 |
rate_limit_7d | USD cap on the rolling 7-day window. | 0 |
ip_whitelist | List of CIDR blocks the key is allowed to call from. Empty = allow all. | [] |
ip_blacklist | List of CIDR blocks explicitly denied. | [] |
custom_key | Optionally supply your own secret string instead of letting the gateway generate one. Useful when migrating from another provider’s key infrastructure. | gateway-generated |
Key lifecycle
Create
GET /v1/keys return a masked
form (sk-byts-...****1234).
Rotate
POST /v1/keys/{id}/rotate re-rolls the secret in place. The old
secret stops working immediately on rotation — there’s no
overlap window. Plan deploys accordingly: roll your config + verify
on the new secret before invoking rotate, or use two keys with
staggered rotations.
Reveal
GET /v1/keys/{id}/reveal returns the plaintext for a key you
already have access to. Useful for recovery flows where the operator
has lost their copy but is still authenticated.
Delete
DELETE /v1/keys/{id} — immediate, no undo. Pending requests using
that key in-flight get a 401 mid-stream.
Failure modes
The error envelope matches the protocol you called. Anthropic shape:| Scenario | HTTP | OpenAI code | Anthropic type |
|---|---|---|---|
| Missing or malformed key | 401 | invalid_api_key | authentication_error |
| Revoked / deleted key | 401 | invalid_api_key | authentication_error |
| Key valid but expired | 401 | invalid_api_key | authentication_error |
IP outside ip_whitelist | 403 | permission_denied | permission_error |
IP matches ip_blacklist | 403 | permission_denied | permission_error |
| Quota / rate-limit exhausted | 402 | insufficient_balance | permission_error |
| Model not in the key’s routing group | 503 | api_error (no available account) | api_error |
Programmatic key management
The full management surface lives under/api/v1/keys. Cookie auth
(from the console) and x-api-key auth (with any active key) both
work.
| Verb + path | What it does |
|---|---|
GET /api/v1/keys | List your keys (masked secrets) |
GET /api/v1/keys/{id} | One key (masked) |
GET /api/v1/keys/{id}/reveal | Plaintext (use sparingly) |
POST /api/v1/keys | Create |
PUT /api/v1/keys/{id} | Update name / quota / rate limits / IP rules / status |
POST /api/v1/keys/{id}/rotate | Re-roll secret in place |
DELETE /api/v1/keys/{id} | Hard delete |
Test a key before shipping
Console → Models has a Test button next to every model. The console picks the right key from your set automatically — the one whosegroup_id actually
matches the model. A 200 there confirms key + group + model all
line up before you commit to wiring it into a client.
You can also dial test from the API: