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:

PrefixEnvironment
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:

ScopeGrants
boats.readGET /v1/boats, GET /v1/boats/:idOrSlug
manufacturers.readGET /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 subscriptionYour existing keys
Active or trialingWork normally
Payment failed, card being retriedKeep working — this is the grace window
Cancelled, or payment retries exhaustedDisabled; requests return 401 INVALID_API_KEY
Re-subscribed after a lapseThe 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

ConditionStatusError code
No Authorization header, or a malformed one401MISSING_API_KEY
Credential passed in the query string401MISSING_API_KEY
Unknown, revoked, disabled, expired or wrong-environment401INVALID_API_KEY
Valid key, but missing the scope the endpoint needs403INSUFFICIENT_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.