API keys
A Headcode key is a credential, not a capacity allowance. Your plan’s limits belong to the account, and keys are how you divide that access up: one per environment, one per service, or a tightly scoped key for anything public-facing. This page covers how many keys each plan allows and how to use them well.
Keys belong to an account
Section titled “Keys belong to an account”Daily requests and burst are held at the account level. Every key you create draws from the same shared budget, so creating more keys does not give you more capacity. To raise capacity, add a volume or throughput pack (see Plans and rate limits).
That leaves keys to do the job they are good at: isolating access. A leaked or misbehaving key can be revoked on its own, and a key can be restricted to only the data a given service needs.
How many keys
Section titled “How many keys”| Plan | Live keys |
|---|---|
| Free | 2 |
| Starter | 5 |
| Pro | 25 |
| Enterprise | Custom |
The limit counts live keys. Test keys (below) do not count towards it. Free allows 2 rather than 1 so you can rotate a key without downtime: create the replacement, cut over, then revoke the old one.
These counts are deliberately loose. Most accounts use a handful, and the limit is there to keep an account tidy rather than to charge for keys. Capacity is sold through packs, never through key count.
When an account is at its limit, creating another key returns 403:
{ "status": 403, "code": "HEADCODE.GENERAL.FORBIDDEN", "detail": "Key limit reached. The Starter plan allows 5 live keys. Revoke an unused key or upgrade to add more."}Scoped keys
Section titled “Scoped keys”A key can hold a subset of the account’s entitlements rather than all of them. A public departure-board widget can use a key limited to boards:read, while the backend that powers it uses a fuller key. If the widget key leaks, the exposure is one read-only scope, not the whole account.
A key’s effective scopes are the intersection of two things: what the account is entitled to, and what the key was granted. So if you later drop the performance add-on, every key that carried performance:read loses it at once, with no per-key changes needed. Scoped keys are available on every plan.
Environments
Section titled “Environments”Keys are prefixed by environment. Live keys begin hc_ and run against production data and your live quota. Test keys begin hc_test_, run against the sandbox, sit outside the live-key count, and do not draw on the live allowance, so wiring up CI or local development does not burn through your daily requests.
Key lifecycle
Section titled “Key lifecycle”Every key can be named and shows a last-used timestamp, so you can tell which key belongs to which service and spot ones that are no longer in use. Revoking a key takes effect immediately and affects only that key, which is the whole reason for issuing a separate key per service.
On Pro and above, keys can also be given an expiry date for scheduled rotation, so a key retires automatically rather than relying on someone remembering to revoke it.
Managing keys in the dashboard
Section titled “Managing keys in the dashboard”Keys are self-service. Sign in at app.headcode.dev (see Authentication for how sign-in works), open Keys, and choose Create an API key.
Creating a key
Section titled “Creating a key”The Create an API key form asks for three things: a label, an environment (live or test), and the scopes to grant. The scope checklist offers exactly what your plan is entitled to — upgrade or add a data product and new scopes appear; there is nothing to unlock per key. MCP access is not offered from the dashboard.
When the key is created, its full value is shown once, on the page that follows. Copy it then: afterwards the dashboard only ever shows the key’s prefix, and the full value cannot be recovered — not by us either, since only a hash of it is stored. If you lose a key, revoke it and create a replacement — that is the supported recovery, and it is a moment’s work in the same page.
Reloading the page cannot mint a duplicate: re-submitting the same form tells you it has already been submitted and creates nothing.
Editing a key’s scopes
Section titled “Editing a key’s scopes”A key’s granted scopes can be changed after creation from Keys → Scopes, bounded by the same entitlement rule as creation. Narrowing a key takes effect on its next request, with no need to rotate it.
After a plan upgrade, the key list flags any active key that lacks a newly available scope and offers a one-click way to add the missing scopes — existing keys do not pick up new entitlements by themselves, because a key’s grants are exactly what you chose them to be.
Rename, revoke, and expiry
Section titled “Rename, revoke, and expiry”Each key row links to its controls: rename (labels are display-only), revoke (behind a confirmation naming the key, effective immediately, freeing a live-key slot at once), and — on Pro and Enterprise — setting or clearing an expiry date. Revoked keys stay listed under Revoked keys for your records; they are never deleted.
Hitting your plan’s live-key limit shows the same message the API returns, quoted above. Test keys are exempt from the limit.
A sensible setup
Section titled “A sensible setup”For a typical production app:
- A backend key with the full set of scopes the app needs.
- A separate, narrowly scoped key for any public or client-side surface (often just
boards:read). - Distinct keys per environment, so a mistake in staging cannot exhaust production’s budget or be confused with it.
This keeps the blast radius of any single leaked key small, and means revoking one never takes down the others.