Skip to main content
This page is for whoever creates, stores and retires OpenType API keys. It explains what a key is made of, what OpenType keeps and what it never keeps, how revocation and rotation behave, and the exact steps to take when a secret leaks.

Anatomy of a key

A key has an id, a secret and a display prefix. Only the secret is a credential. The otsk_ prefix makes a leaked secret easy to find with a secret scanner. The 64 hex characters that follow are randomly generated.

What OpenType stores

  • Verification hashes the secret you send and compares digests in constant time.
  • The server never writes the secret to its logs.
  • Because only the digest is kept, OpenType cannot show you a secret again, and neither can anyone who reads the stored key data.

The secret is shown once

The plaintext secret appears in exactly two responses: Put the secret in a secret manager, or your platform’s encrypted environment variables, before you do anything else with the response. If you lose it, you cannot recover it: rotate the key or create a new one.

Create a key

This creates a key that can send runs and read them back. The calling credential needs keys_write. See Scopes and roles for choosing scopes.
The console does the same in two steps and shows the secret once on the second:
Newly created key showing its secret once, with a Copy secret button and the key's id, prefix and scopes

Key object fields

There is no expires_at: keys do not expire.

Lifecycle rules

Find unused keys

List every key in your organization and look at state and last_used_at. This needs keys_read. The list is newest first and never contains secrets.

Revoke a key

DELETE /v1/keys/{key_id} needs keys_write. Pass the key_ id, never the secret.
You can also revoke from the console:
Revoke key dialog warning that the key stops working immediately and cannot be re-enabled

Rotate a key

POST /v1/keys/{key_id}/rotate issues a new secret for the same key. The id, name and scopes stay the same, and the response carries the new secret once. Rotation is available through the API only.
The old secret stops working the moment the rotation succeeds. There is no grace period. Every process still holding the old secret gets 401 invalid_credential until it has the new one. For a zero-downtime change, create a second key, deploy it, then revoke the first. See Key rotation.
Do not rotate a key using that same key unless the calling process can switch to the new secret before its next request.

If a secret leaks

A secret counts as leaked once it has been anywhere other than your secret store and the Authorization header of a request to https://api.opentype.dev: a commit, a chat message, a ticket, a log line, a screenshot, a URL, or client-side code.
1

Find the key

Match the first 13 characters of the leaked value against secret_prefix in GET /v1/keys or in the console key list. Note its id.
2

Kill the leaked secret

If you can redeploy right away, rotate the key. The leaked secret stops working immediately and the key keeps its id and scopes. If you cannot redeploy right away, create a replacement key first, deploy it, then revoke the leaked one. Every minute in between, the leaked secret still works.
3

Deploy the new secret

Update every process that held the old secret. Watch for 401 invalid_credential in your logs, which shows a process you missed.
4

Check what it did

Review usage and the run list for activity you do not recognize, and look at the key’s last_used_at.
5

Remove the copy

Delete the secret from wherever it leaked. Removing it from git history alone is not enough, because the secret stays valid until you complete step 2.

A secret in a URL path

Key routes take the key_ id in the path. If the path value starts with otsk_, the request is refused before any lookup:
Treat 400 secret_in_path as a leak. URLs end up in access logs, proxy logs and browser history, so rotate that key now, then fix the code to pass the id field.

Key route errors

Storage checklist

  • Keep secrets in a secret manager or encrypted environment variables, never in source control or container images.
  • Never send a key to a browser or a mobile app. Call OpenType from your server.
  • Log the key id or secret_prefix, never the secret. Scrub Authorization headers from your own request logs.
  • Use one key per process and environment, named after what holds it, so you can revoke one without touching the others.
  • Add a secret scanner rule for otsk_[0-9a-f]{64} to your repositories and CI.