Provisioning Keys
A provisioning key lets your backend create and manage inference API keys programmatically — without anyone logging into the Console. Ideal for SaaS products that issue one key per end-customer, per device, or per CI job.
A provisioning key can create, modify, and delete any inference key in its workspace. Treat it like an admin credential: store it server-side only and never ship it to browsers or mobile clients.
How it works
- An owner or admin creates a provisioning key in Console → Provisioning Keys. It carries the prefix
sk-syn-prov-. - Your backend calls the
/api/provisioning/*endpoints with that key to create inference keys (prefixsk-syn-). - Each inference key is scoped to the same workspace and can carry a USD spending cap and opaque
metadatatags. - Hand the inference keys to your customers. Revoke any of them individually at any time — deleting a provisioning key does not affect the inference keys it already created.
Provisioning keys themselves are created in the Console only — there is no API to mint a provisioning key. Open Console → Provisioning Keys (owner / admin only).
Authentication
Pass the provisioning key as a Bearer token. It works only on /api/provisioning/* — a provisioning key cannot make inference calls, and a regular inference key cannot call these management endpoints (both return 401 wrong_key_kind).
Authorization: Bearer sk-syn-prov-... Create an inference key
POST /api/provisioning/keys
| Parameter | Type | Description |
|---|---|---|
name | string | Human-readable label for the key (e.g. "Device abc-123"). |
quota | number | Spending cap in USD. Omit or set 0 for unlimited. |
allowed_models | string | Comma-separated model allowlist (e.g. "claude-haiku-4-5"). Empty = all models the workspace can access. |
ip_whitelist | string | Comma-separated IP / CIDR allowlist for requests made with this key. Empty = no restriction. |
expires_at | string | Optional RFC3339 expiry timestamp. Omit for no expiry. |
include_byok_in_limit | boolean | If true, BYOK calls count toward this key’s quota at upstream list price. Default false. |
metadata | object | Opaque JSON tags you define (e.g. {"tenant_id":"acme"}). Stored verbatim, max 8KB. Used for listing / filtering only — never affects auth. |
curl https://synthorai.io/api/provisioning/keys \
-H "Authorization: Bearer sk-syn-prov-..." \
-H "Content-Type: application/json" \
-d '{
"name": "Device abc-123",
"quota": 5.0,
"allowed_models": "claude-haiku-4-5",
"metadata": { "tenant_id": "acme", "device_id": "abc-123" }
}'import requests
resp = requests.post(
"https://synthorai.io/api/provisioning/keys",
headers={"Authorization": "Bearer sk-syn-prov-..."},
json={
"name": "Device abc-123",
"quota": 5.0,
"allowed_models": "claude-haiku-4-5",
"metadata": {"tenant_id": "acme", "device_id": "abc-123"},
},
)
inference_key = resp.json()["key"] # full key — shown only onceThe response returns the full key in the key field exactly once. Store it immediately — it cannot be retrieved later.
{
"id": 42,
"key": "sk-syn-d4f0...e91b",
"key_prefix": "sk-syn-d4f0...",
"name": "Device abc-123",
"kind": "inference",
"created_via": "provisioning_api",
"parent_provisioning_id": 7,
"workspace_id": 11,
"quota_usd": 5.0,
"unlimited_quota": false,
"allowed_models": "claude-haiku-4-5",
"metadata": { "tenant_id": "acme", "device_id": "abc-123" },
"created_at": "2026-06-01T12:00:00Z"
} List inference keys
GET /api/provisioning/keys
Lists every inference key in the workspace. Filter by any metadata field with ?metadata.<key>=<value>; multiple filters are combined with AND.
# all keys
curl https://synthorai.io/api/provisioning/keys \
-H "Authorization: Bearer sk-syn-prov-..."
# only keys tagged tenant_id=acme
curl "https://synthorai.io/api/provisioning/keys?metadata.tenant_id=acme" \
-H "Authorization: Bearer sk-syn-prov-..." Retrieve, update & delete
Address a single inference key by its numeric id:
- GET
/api/provisioning/keys/{id}— fetch one key. - PATCH
/api/provisioning/keys/{id}— updatename,quota,status,allowed_models,ip_whitelist,expires_at,include_byok_in_limit, ormetadata. Thekindand lineage fields cannot be changed. - DELETE
/api/provisioning/keys/{id}— revoke a key. Effective immediately.
# disable a key (status 2 = disabled)
curl -X PATCH https://synthorai.io/api/provisioning/keys/42 \
-H "Authorization: Bearer sk-syn-prov-..." \
-H "Content-Type: application/json" \
-d '{ "status": 2 }'
# delete a key
curl -X DELETE https://synthorai.io/api/provisioning/keys/42 \
-H "Authorization: Bearer sk-syn-prov-..." Quotas & spend control
quota is a USD cap per inference key. Usage is metered after each request, so a key may slightly exceed its cap within a short settlement window under heavy concurrency — size caps with a small buffer for high-value models. Read a key's current spend from used_usd in the list / retrieve responses.
Tag keys at creation with metadata (tenant, device, environment) so you can list, audit, and bulk-revoke them later by filter. Keys created this way also appear in Console → API Keys with a Programmatic source badge and their tags.
Sizing per-key USD caps? The LLM API cost calculator converts a customer's expected token volume into a monthly spend figure you can set as the quota.