Keys and secrets
- One key per environment and per service. Development, staging and production each get their own key, named after the process that holds it. Rotating or revoking one then touches nothing else. See Key rotation.
- The smallest scope set on each key. A service that sends runs needs
runs_writeandruns_read. A dashboard needsusage_readandbilling_read. Only the tool that manages keys needskeys_readandkeys_write. Scopes are fixed when a key is created. See Scopes and roles. - The secret lives in a secret store, not in source code, container images, build logs or client-side code. Load it into
OPENTYPE_API_KEYat runtime. The secret is shown once, at creation or rotation, and cannot be recovered. See API key security. - Calls come from your servers, not from browsers or mobile apps. Anyone who can read a secret can spend your credit.
- A key id, never a secret, goes in a URL. A secret in a key route’s path is refused with
400 secret_in_path; treat that secret as leaked and rotate it. - A rotation plan exists. Keys never expire. Decide how often you rotate, who does it, and how you roll out a new secret without downtime. See Key rotation.
Requests
- Every
POST /v1/runscarries anIdempotency-Keyderived from your business id, such asticket-4822-triage, not a random value per attempt. A key is 1 to 255 bytes of visible header text, unique per organization, and never expires. See Idempotency. - A changed body gets a new key. Reusing a key with a different body is refused with
409 idempotency_conflict. Append an attempt suffix, such asticket-4822-triage-r1. -
deadline_msis set on purpose. For a decision run it defaults to 30,000 plus 120,000 per 262,144 input tokens and is clamped to 1 to 150,000. A run that misses it fails with504 deadline_exceeded. - Your HTTP client timeout is longer than
deadline_ms.POST /v1/runsanswers only when the run has settled. Use at least 160 seconds, 10 seconds over the longest deadline; the official SDKs default to 170 seconds. - A client timeout is recovered by resending the same request with the same key. You get the stored run back instead of a new one:
200withreplayed: trueonce it has settled,202while it has not. A replay is never charged. See Polling. -
max_output_tokensis close to what the answers need. It is required, and counts in full against a token quota at admission. - Decision inputs stay under 262,144 tokens. The estimate is the bytes of
statedivided by 4, rounded up, plus the bytes of the question set (instructions,questions,drawsandthink_tokens) divided by 4, rounded up. Above 262,144, the run is refused with413 input_too_large. See Models and pricing. - Bodies stay under 4 MiB. Larger bodies are refused with
413 body_too_large. - The model is set on purpose. Decision runs take an optional
model:"neon-1.1"or"neon-latest". Any other value is refused with400 unknown_model.
Observability
- You send your own
x-request-idon every call and log it next to your business id. A value of 1 to 128 characters fromA-Z a-z 0-9 . _ -is echoed back; anything else is replaced by a server id. See Request ids. - You log the
x-request-idresponse header anderror.request_idfor every failure. It is the value to quote when you ask about a request. - You log
run_id,cost_microsandusagefrom each run, so your records join the usage ledger. - You branch on
error.code, never onmessage. Messages are for people and can change. See Error handling. - You handle bodies that are not JSON. A few framework refusals on non-run routes (malformed JSON, a wrong
Content-Type, an unknown field or query parameter) return plain text with norequest_idin the body. Fall back to the status and thex-request-idheader.
Error handling
- Retries are bounded: a few attempts with exponential backoff and jitter, then an alert.
- The policy comes from the status and
error.code, as in the table above. See Error handling.
Credit and spend
- Auto-recharge is on, with a card saved, a threshold above one hour of spend plus 20,000 micros, and an amount above your busiest hour. It charges at most once per organization per clock hour. See Auto-recharge.
- The balance covers your concurrency. Every run in flight holds its spend ceiling, up to 20,000 micros ($0.02), until it settles.
- A balance alert exists, fed by
GET /v1/billing, that fires beforebalance_microsgets near zero. - A quota alert exists, fed by
GET /v1/quota, that fires whenremaining_spend_microsorremaining_tokensfalls below one normal day’s use. - Someone reviews spend with
GET /v1/usage/dailyor the console Usage page. - Billing permissions are in the right hands. Only owners, admins and billing users hold
billing_write.
Before the switch
Run these once from the production environment.OPENTYPE_API_KEY is the production runtime key; OPENTYPE_MONITOR_KEY is a separate key with usage_read and billing_read for your monitoring.
completed run with a small cost_micros, room left in the quota (or null limits), a positive balance, and auto-recharge enabled with a saved card.
Related
- Code examples - complete clients that implement this checklist.
- Error handling - the full status-to-action policy.
- Key rotation - replace a secret without downtime.
- Auto-recharge - keep the balance funded.
- Limits - every size, count and time limit in one place.