API Docs

Authentication

Every request to /api/v1/* carries an API key as a Bearer token. Keys are scoped to a single integration and can be regenerated at any time.

Header shape

Authorization: Bearer wth_YOUR_API_KEY

The scheme is Bearer. The token is your full API key, prefix included. There is no other auth mode. Basic auth, query params, cookies, and HMAC-as-auth all return 401.

Key format

Keys are 36 characters: the literal prefix wth_ followed by 32 base62 characters (A-Z, a-z, 0-9). The full regex used at the door:

/^Bearer\s+(wth_[A-Za-z0-9]{32})$/

The 32-character body comes from a CSPRNG and gives ~190 bits of entropy. Only the SHA-256 hash is stored server-side. The plaintext is shown exactly once at generation time and never again.

Generate a key

From the dealer dashboard, open Custom Integration → Settings and click Regenerate key (or Generate API key on a fresh integration). A modal reveals the full key. Store it in a secrets manager: env vars for your deployment, 1Password, AWS Secrets Manager.

Lost your key?

There is no recovery. The plaintext only exists in the modal that appeared at generation. If you lost it, regenerate. The previous value is invalidated immediately and any client still using it will get 401 invalid_api_key on the very next call.

Rotation

Regenerating a key is the rotation. There is no overlap window. The moment you click confirm, the old key's hash is overwritten and the new key's hash takes its place. Roll out the new key to all clients in the same deploy or you will see 401s.

We recommend rotating after every team-member offboarding that had access to the secrets store.

Webhook signing secret rotation works differently: the previous secret remains valid for a short overlap window while you roll out the new value. See the Webhooks page for details.

Auth failures

Three different 401 responses tell you why auth failed. Branch on code, not on the human-readable message:

CodeMeaning
missing_authorizationThe Authorization header was absent. Often a proxy strip.
malformed_authorizationThe header didn't match Bearer wth_[A-Za-z0-9]{32}. Wrong scheme, wrong prefix, wrong length.
invalid_api_keyThe key is well-formed but doesn't match any active integration. Was it regenerated?

A separate 403 with code integration_disabled fires if the dealer has paused the integration.

Rate limit headers

Every authenticated response (200 or otherwise) carries:

X-RateLimit-Limit: 600
X-RateLimit-Remaining: 597
X-RateLimit-Reset: 1778230107
X-Request-Id: req_a4e6109f47be44a3a017ad94965e1a66
X-API-Version: 2026-05-07

Quote X-Request-Id in any support ticket. It points at a single row in our api_request_logs and shortens triage by an order of magnitude. See Rate limits for the full window mechanics.