Skip to main content
The /v1 API has three authentication models depending on the surface you call.

API keys (headless data plane)

Headless quote routes authenticate with a secret API key as a bearer token. There is no OAuth flow and no token refresh — the key is the credential. The prefix is not cosmetic: the key record binds a Workspace, Project, and one Environment, and a key can never address the other Environment’s data.
A missing or malformed key returns 401 with code: "invalid_api_key".

Key storage

Only the SHA-256 digest of a key is stored. The plaintext secret is returned exactly once — at creation — and the Console shows only a display prefix and the last four characters afterward.
Never expose a Live key in client-side code, public repositories, or logs. Browser-facing surfaces must use the anonymous public routes or a server-side proxy, never a raw sk_ key.

Key lifecycle

Any Workspace member with the api_keys:create permission can create keys for the Test or Live Environment — in the Console Developers section, or with POST /v1/api-keys. The generated prefix follows the Environment.
  • Rotate with POST /v1/api-keys/{keyId}/rotation. The response carries the successor’s secret (shown once); the predecessor keeps working for a grace window — graceMinutes, default 24 hours, 0 for no overlap — then revokes automatically. Grace expiry is enforced by the platform’s delivery sweep, so it is as precise as that schedule (about a minute); use graceMinutes: 0 when overlap is unacceptable.
  • Revoke with POST /v1/api-keys/{keyId}/revocation. Immediate and idempotent; the key stops authenticating at once.
  • A revoked or not-yet-swept key in a grace window is never re-shown — secret material is only ever returned at creation and rotation.

Webhook signing secrets

Webhook endpoints carry a second credential type: a signing secret (whsec_…), shown once at endpoint creation and rotation. Unlike API keys, signing secrets are stored reversibly — the platform must read them to sign deliveries — while API keys are stored as one-way SHA-256 digests. Signing secrets never authenticate API requests; they only verify that a webhook delivery came from Kordless. See Webhooks.

Business-member sessions (hosted portal routes)

Routes under /v1/businesses/{businessId}/… authenticate the caller’s Clerk session and authorize against their Business membership:
  • POST /v1/businesses/{businessId}/quotes — any active member can quote; the Live Environment is pinned server-side.
  • GET /v1/businesses/{businessId}/members — any active member can list the roster.
  • PATCH / DELETE /v1/businesses/{businessId}/members/{membershipId} — Business Owner only (403 not_business_owner otherwise).
  • PUT /v1/businesses/{businessId}/branding — a Workspace member with businesses:manage, or a Business Owner on a Direct (self) connection.
An unauthenticated call returns 401 with code: "unauthorized". These routes are used by the Business Portal and are also callable from your own server with the member’s session.

Anonymous public routes

End-customer routes require no credential at all:
  • POST /v1/public_quotes — create a Quote against a Business’s Live-published Book.
  • GET /v1/public_quotes/{quoteIntentId} — retrieve that Quote.
Anonymous access is safe because the data plane scopes it: only Businesses with an active connection and a Live publication are quotable, reads are restricted to end-customer hosted Quotes (member and API-key Quotes return 404), and the surface configuration exposes ids and labels only — never prices before submission.

What authentication does not do

  • Authentication does not authorize Book authoring or publication. Those are Workspace/Business operations with their own role checks.
  • Authentication does not bypass idempotency. Every write still accepts an idempotencyKey — see Idempotency.
  • An API key’s Environment binding cannot be overridden by request parameters. There is no mode-switching parameter — see Test and Live.