Authentication

Every API call carries an app token as a bearer credential:

GET /v1/answers/current-place HTTP/1.1
Host: api.contextkit.com
Authorization: Bearer cka_3f9a…

Getting a token

  1. Register your app on the Apps page, declaring the scopes it may ever request. This is the maximum a user can grant — you can always narrow later, and shrinking takes effect immediately for existing tokens.
  2. A user connects it. They tick scopes individually, choose which places you may ask about, and pick an expiry.
  3. The token is shown once. Store it then; we keep only its SHA-256 and cannot show it again. Lost tokens are re-minted by disconnecting and reconnecting, which the user has to do.

One token represents one user's authorization of one app. It is not an API key for your service — if ten people connect your app, you hold ten tokens.

New apps start in sandbox tier: only the developer who registered it can connect. Promoting to production requires an approved developer application and opens it to everyone.

What a token carries

A token is bound to the scopes the user actually approved, which may be fewer than you requested. The effective set is the intersection of what the user granted and what your app currently declares, so an admin narrowing your app's scopes bites live tokens without any migration.

Calling an endpoint whose scope you don't hold returns 403, not 404 — you can tell the difference between "not permitted" and "doesn't exist."

Failures

StatusMeaningRetry?
401Missing, malformed, revoked, or expired tokenNo — the user must reconnect
403Valid token, missing scopeNo — request the scope, or drop the call
404Resource doesn't exist, or isn't visible to youNo
429Rate or budget limitYes, with backoff — see Errors and limits

An expired grant is indistinguishable from a revoked one: both are 401. Treat either as "this user is gone until they reconnect," and don't retry.

Errors use the standard NestJS shape:

{
  "statusCode": 403,
  "message": "grant is missing scope location.visits.read",
  "error": "Forbidden"
}

message is sometimes an array when several validation errors apply at once.

Handling disconnection well

Users disconnect. When they do, every one of your calls starts returning 401 and your webhook rules stop firing — silently, from your side.

Detect it and stop calling. An app that keeps hammering a dead token burns your rate limit, and doing it across many users looks like exactly the kind of behaviour our abuse detection exists to catch.

If you promised the user you'd delete their data on revocation — and your developer application attested that you would — this is the signal to do it.

Keeping tokens safe

  • Store them encrypted at rest. They authorize questions about a real person.
  • Never put a token in a URL. Query strings end up in access logs, proxy logs, and browser history. Use the Authorization header.
  • Use one token per user, never a shared one.
  • There is no refresh flow. A token lives until it expires or the user revokes.