Authentication
Meridian Blue uses bearer-token authentication. Every API key carries a credit limit, a rate-limit override, and an optional expiry — created and rotated from the dashboard.
Bearer token
Every request must include the API key in one of three header formats (see below). Keys are created, edited, and revoked from the dashboard.
POST /v1/chat/completions HTTP/1.1
Host: api.meridianblue.ai
Authorization: Bearer kp_live_xxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
Supported header formats
The same key works through any of these headers — useful when you want to point an SDK that expects a different header at Meridian Blue.
| Header | Typical SDK |
|---|---|
Authorization: Bearer kp_live_… | OpenAI, Groq, Cohere, Mistral, OpenRouter |
X-Api-Key: kp_live_… | Anthropic |
x-goog-api-key: kp_live_… | Google Gemini |
Key format
Every key starts with kp_live_ followed by 24 random bytes (URL-safe). One prefix, no test/live distinction at the key level — billing and spend caps are per-key configuration on the dashboard.
kp_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2
Permissions
Permissions are tied to your account role on the dashboard, not to the individual key. The roles today:
| Role | Can do |
|---|---|
owner | Everything: model catalogue management, billing, role changes, hard deletes. |
admin | Manage models, users, policies, credits — but cannot transfer ownership or hard-delete catalogue rows. |
billing | Top up credits, manage payment methods, view billing history. |
auditor | Read-only access to usage, conversations, and audit logs. |
reviewer | Approve/reject items in the human-review queue (Article 14 oversight). |
user | Manage own keys, view own usage, send inference requests. |
tester | Internal — see the dashboard chat playground for SDK testing. |
The allowHighRisk flag is set per-key and is required to send requests classified as high-risk under the EU AI Act. See Risk classification.
Spend caps
Each key has an optional creditLimit (in credits; null = no limit). Once creditsConsumed >= creditLimit the key returns 402 Payment Required and stops billing.
Webhooks fire once per billing cycle as the key crosses each threshold:
| Threshold | Webhook event |
|---|---|
| 50% | spend.50_percent |
| 80% | spend.80_percent |
| 100% | budget.exceeded |
Idempotency is enforced at the database level — even under concurrent requests crossing a threshold, each event fires exactly once until the next reset. See Webhooks for the payload shape.
The credit counter resets on the schedule set by the key's resetInterval:
never— lifetime cap.daily/weekly/monthly— counter resets back to zero on the boundary.
Rate limits
Each key carries a single rateLimit override (requests per minute). When unset, the global default of 60 req/min applies. Burst over the limit returns 429 Too Many Requests.
Free-tier accounts also have a daily multimodal-request cap (default 5/day) on top of the per-minute limit. Paid and enterprise tiers transition to credit billing instead of being hard-blocked.
Expiry
Keys can carry an expiresAt timestamp. After that timestamp, requests return 403 key_expired and the key cannot be re-enabled — create a new one. Use this to scope CI keys, demo keys, or vendor-shared keys to a fixed window.
Rotation & revocation
To rotate a key with no downtime: create a new key on the dashboard, deploy it, then revoke the old one. Revoked keys return 403 invalid_api_key immediately. The audit log keeps revoked keys' attribution intact, so historical usage is still queryable.