Authentication
Every /v1 endpoint except the version root requires an API key, sent as a bearer token:
curl -s "https://api.theboatdb.com/v1/boats" \
-H "Authorization: Bearer tbdb_live_3ZKjq9xVn2..."That is the only accepted transport. There is no ?api_key= query parameter, and a request that
looks like it is carrying a credential in the query string is rejected with a message telling you to
rotate it — a key in a URL has already been written to access logs, proxy logs and CDN cache keys by
the time it reaches us.
Key format
Keys are prefixed by environment and carry 24 random bytes:
| Prefix | Environment |
|---|---|
tbdb_live_ | Production |
tbdb_test_ | Staging and local work |
The prefix makes a key recognisable in a log line or a support ticket, and greppable by secret
scanners. The two environments are completely separate: a tbdb_test_ key does not exist in
production and is rejected there with INVALID_API_KEY, and the reverse is equally true. Pointing
a staging integration at production is a 401, not a surprise bill.
Scopes
Each key carries an explicit set of permissions, and each endpoint declares the one it needs:
| Scope | Grants |
|---|---|
boats.read | GET /v1/boats, GET /v1/boats/:idOrSlug |
manufacturers.read | GET /v1/manufacturers, GET /v1/manufacturers/:idOrSlug |
GET /v1/manufacturers/:idOrSlug/boats spans both resources and requires both scopes. A key
holding only manufacturers.read cannot reach boat data through the nested path.
New self-service keys are issued with both scopes. Scopes are assigned by us, not requested by you: the create-key form takes a name and an optional expiry, and nothing else — so a key cannot widen its own access, and a permission we add in future is not retroactively granted to keys that already exist.
Expiry and revocation
Keys do not expire by default. A working integration should keep working until somebody revokes it deliberately, rather than breaking on an anniversary nobody wrote down. You can opt into an expiry when you create a key, up to a maximum of 365 days.
Revocation takes effect on the next request — nothing about key validity is cached, so there is no window in which a revoked key still works. If a key leaks, revoke it in the dashboard and the exposure ends immediately.
The full key is displayed once, when you create it. We store a hash, not the key, so we cannot show it to you again or recover it for you. If it is lost, revoke it and create another.
Subscription changes
API keys require an active Pro subscription, and that is re-checked continuously rather than only at creation time.
| Your subscription | Your existing keys |
|---|---|
| Active or trialing | Work normally |
| Payment failed, card being retried | Keep working — this is the grace window |
| Cancelled, or payment retries exhausted | Disabled; requests return 401 INVALID_API_KEY |
| Re-subscribed after a lapse | The same keys are restored — no re-issuing needed |
A failed renewal does not take a deployed integration offline. Keys stay live for as long as your card is being retried, and are only disabled once the subscription is actually cancelled. If that happens we email the key owner, because the request that starts failing belongs to a server, not to someone sitting in front of a browser.
Keys that you revoked yourself, or that our support team disabled, are not brought back by re-subscribing. Only keys disabled for a lapsed subscription are restored.
Managing keys
Create, list and revoke keys in your dashboard. Key management is a separate surface from the data API and is authenticated by your signed-in session — an API key cannot be used to mint or revoke another API key, so a leaked key cannot be used to entrench itself.
Keeping keys safe
- Store the key in your deployment environment's secret manager, not in the repository.
- Never ship it in a browser bundle or a mobile app. Anything shipped to a client is public; proxy through your own backend instead.
- Use a separate key per integration, so revoking one does not take down the others.
- Rotate by creating the new key, deploying it, and revoking the old one — in that order, with no gap in which neither works.
If you believe a key has been exposed, revoke it first and investigate afterwards. Contact [email protected] if you need help.
Failure reference
| Condition | Status | Error code |
|---|---|---|
No Authorization header, or a malformed one | 401 | MISSING_API_KEY |
| Credential passed in the query string | 401 | MISSING_API_KEY |
| Unknown, revoked, disabled, expired or wrong-environment | 401 | INVALID_API_KEY |
| Valid key, but missing the scope the endpoint needs | 403 | INSUFFICIENT_PERMISSIONS |
A 401 means fix the credential. A 403 means the credential is fine but the key is not allowed to do this — retrying will not help, and neither will rotating the key. See Errors for the full set.