API keys & service principals
Scoped, expirable, hashed API keys for backend access, and service principals for OAuth client_credentials.
Machine identities come in two shapes. Use whichever fits your call pattern.
API keys
An API key (qk_…) authenticates your backend to the Qeet ID API. Keys are
hashed at rest, can be scoped and expirable, and are sent as:
Authorization: ApiKey qk_…/v1/api-keysCreate an API key (secret shown once)/v1/api-keysList API keys/v1/api-keys/{id}Revoke an API key/v1/tenants/{tenantID}/api-keysList a tenant's API keyscurl -X POST https://api.qeetid.com/v1/api-keys \
-H "Authorization: Bearer $QEETID_ADMIN_TOKEN" \
-d '{"name":"backend"}'
# → { "id": "…", "key": "qk_…" } ← shown onceServer-only, shown once
The full qk_… value is returned only at creation — store it in a secret
manager immediately. Never ship an API key to a browser; for client apps use the
hosted-login flow (@qeetid/nextjs).
ApiKey, not Bearer
API keys use the ApiKey scheme. The Bearer scheme on the
same routes is for user/service JWTs. Don't mix them.
Service principals
A service principal is an OAuth client for M2M access via
client_credentials. Use it when a machine needs a standard OAuth access token (e.g.
to call your own resource servers), rather than direct Qeet ID API access.
/v1/service-principalsCreate a service principal/v1/oauth/tokenGet a client_credentials tokenSee OIDC → Machine-to-machine for the full flow.
Which should I use?
| Need | Use |
|---|---|
| Backend calling the Qeet ID API | API key (ApiKey qk_…) |
| Machine client needing an OAuth access token | Service principal (client_credentials) |
| Per-user backend call | the user's access token (Bearer <jwt>) |