API keys
- 1 endpoint
An API key belongs to one space (spaces): the organization's shared space, where it acts as an admin of the organization, or a member's personal space, where it acts as that member. Its mode (test or live) is the space's.
List API keys#
GET /api-keys
A page of the keys of the caller's space (a member's own keys; the shared keys for the team), newest first, or with includeMembers=true every key of the organization in the request's mode. A member needs the members.apiKeys policy (403 policy_disabled).
- Auth
- X-API-Key: any keyA member's key needs the members.apiKeys policy
- On-Behalf-Of
- Honored: acts in the member's space
- Idempotency-Key
- Ignored
- Success
- 200
request.sh
curl https://api.qbitflow.app/v2/api-keys \ -H "X-API-Key: $QBITFLOW_API_KEY"# 200: a page of ApiKey ({ items, hasMore, nextCursor? })Query parameters
limitintegerOptionalPage size: 20 when absent or ≤ 0, at most 100 (a larger one is clamped, not refused)
cursorstringOptionalThe previous page's nextCursor, verbatim; omit for the first page
max=200includeMembersbooleanOptionalWith true: every key of the organization in the request's mode, its members' included (userUuid names the member), for an owner or admin to find a key to revoke (403 forbidden for anyone else; 400 validation_failed from a member's space). Default false: the request's space's keys
Response
A page: { "items": ApiKey[], "hasMore": …, "nextCursor"?: … }. Pass nextCursor back as cursor for the next page; it is absent when hasMore is false.
9 fields of each ApiKey
uuidstringIts only id (a UUIDv7)
namestringName of the API key
testbooleanWhether this is test data (testnets) or live data
userUuidstringOptionalMember the resource belongs to; omitted for the organization's own resources
Only for the resource's owner
createdByUserUuidstringOptionalWho created the key (omitted once that user is deleted). A shared-space key acts for them in the audit trail, and outlives them
rolestringRole is the most the key acts as, fixed at its creation: admin for the organization's keys, the member's role then for a member's (user). A member's key acts with the lower of it and the member's role now: a demotion narrows it, a promotion never widens it (a member made admin keeps a member's key, which can't act On-Behalf-Of: they create a new key for their new role)
createdAtstringTimestamp when the API key was created
expiresAtstringOptionalWhen the API key expires; absent if it never expires
lastUsedAtstringOptionalWhen a request last authenticated with the key, within the hour (recorded at most once an hour); absent if it never was
Errors
- 403policy_
disabled a member doing what their organization's policy doesn't allow them, reads of what the policy governs included
Also the common codes, as any route (what each means):
- 400validation_failed
- 401unauthorized
- 403forbidden
- 404not_found
- 429rate_limit_exceeded
- 500internal
- 504timeout
Edge cases
The contract's rules for these routes: Authentication & roles · Authentication with a key · List — GET /api-keys · Status-code summary.
Read all 4
Authentication & roles
- Create and delete are dashboard-only: an API key there →
404, so keys never mint or revoke keys. Both need a recent re-authentication (403reauth_required). - A qbf.cash session →
404.
Authentication with a key
- A key whose
live/testlabel was edited (it no longer matches its space) →401. An expired, revoked or malformed key →401. - Keys in the format v1 issued (
sk_<digits>_<live|test>_<secret>) don't authenticate:401unauthorized, like any key whose id part isn't a uuid (or is the nil uuid). They were deleted at the launch:GET /api-keyslists only keys created in v2. A key with its uuid before its mode (sk_<uuid>_<live|test>_<secret>, the format issued until the mode moved first) →401unauthorizedtoo: create a new key. A member's key stops authenticating when the member is removed from that mode (401). - A member's key acts as the member, in their space: it sees their products, not the organization's (and the reverse, without
On-Behalf-Of).
List — GET /api-keys
- A page of keys, newest first (
createdAt, thenuuid), in the list envelope (limit20 by default, at most 100;cursor= the previous page'snextCursor; a cursor that isn't one →400validation_failedoncursor). - Without
includeMembers(orfalse): the keys of the request's space. The team (owner, admins) sees the organization's keys, whoever created them; a member sees only their own;On-Behalf-Ofa member lists the member's. Another organization's keys, and the other mode's, never appear. ?includeMembers=true: every key of the organization in the request's mode, members' keys included (a member's key hasuserUuid, the member; the organization's keys have none), for an owner or admin to find a key to revoke. Below admin in the space (a member, a member's key, an organization key actingOn-Behalf-Ofa member, an owner switched into a member's space) →403forbidden. Switch mode for the other mode's keys.ApiKeynever carries the hashed secret.
Status-code summary
401unauthenticated, or an invalid, expired, revoked or relabelled key.403:includeMembersbelow admin in the space; creating a key as a member without themembers.apiKeyspolicy (policy_disabled), or for a member from the team (forbidden); revoking a key of the organization the caller doesn't manage;reauth_required.404another organization's key or an unknown uuid, and dashboard-only routes with a key.400validation failure.200list,201create,204revoke.
The codes named here
- 400validation_
failed path/query/body failed binding or validation, or a business rule about one input (a field named in
errors) - 401unauthorized
missing / invalid JWT or API key, an ended login
- 403forbidden
authenticated but not allowed (role, peer resource)
- 403policy_
disabled a member doing what their organization's policy doesn't allow them, reads of what the policy governs included