Skip to content
Skip to Content
APIAuthentication and keys

Authentication and keys

Send your key as a bearer token on every request:

Authorization: Bearer doozy_sk_...

A key opens one workspace

A key is created inside a workspace and can only reach that workspace. There is no parameter to point it somewhere else, and an id from another workspace reads as missing rather than forbidden, because telling you a record exists somewhere you cannot reach is itself a leak.

To learn which workspace a key opens:

curl https://api.usedoozy.com/api/v1/me \ -H "Authorization: Bearer $DOOZY_API_KEY"

To work across several workspaces, create a key in each.

What a key looks like

doozy_sk_KFpivWUqE0iq5EhgHGdq70X0VLdhyC2l7Itf8mdk0eJAVI └──┬───┘└──────────────────┬───────────────────┘└──┬─┘ marker 40 random characters checksum

The doozy_sk_ marker is there so a secret scanner can spot a key in a commit, a log or a paste without knowing anything about Doozy. The trailing checksum lets a malformed or truncated key be rejected before it costs anything.

The secret exists once

At creation, the response carries the key itself. That is the only time it exists outside your hands: we store a SHA-256 hash of it and nothing else. If you lose a key, revoke it and create another.

The list of keys shows enough to tell them apart, and no more:

{ "object": "api_key", "id": "d41f...", "name": "Zapier production", "prefix": "doozy_sk_KFpivW", "last4": "JAVI", "scopes": ["todos:read", "todos:write"], "lastUsedAt": "2026-08-20T13:58:00.000Z", "expiresAt": null, "revokedAt": null }

Revoking

Revoking takes effect on the next request that uses the key. There is no grace period and no cache to wait out.

Any member of a workspace can revoke any of its keys. A key that is misbehaving should be stoppable by whoever notices, not only by whoever created it.

Revoked keys stay in the list so the record of what existed, and when it stopped, remains.

Rotating

There is no rotate operation, because rotating in place would leave a window where neither the old key nor the new one is definitely the one in use. Instead:

  1. Create a new key with the same scopes.
  2. Deploy it.
  3. Confirm the old key’s lastUsedAt has stopped moving.
  4. Revoke the old key.

Expiry

A key can be given a lifetime when it is created. An expired key returns expired_api_key and cannot be extended; create a new one.

Keys handed to a third party are worth expiring. Keys running your own production integration are usually better left open and rotated deliberately.

Rate limits

Each key gets 120 requests a minute. Every response carries the budget:

RateLimit-Limit: 120 RateLimit-Remaining: 117 RateLimit-Reset: 43

Past the budget you get 429 with Retry-After in seconds. Read RateLimit-Remaining and slow down before that happens rather than after.

Calling as a signed-in user

You can skip this section if you are integrating with a key.

The API also accepts the session token the Doozy app itself uses, paired with a header naming the workspace:

Authorization: Bearer <firebase id token> X-Doozy-Workspace-Id: 7f2a...

This exists so the app and its own tooling can use the same surface. A session carries every scope, because a signed-in member can already do all of this in the app.

Key management accepts this scheme only. An API key cannot create or revoke API keys: a key that could mint another would make revocation meaningless.

Last updated on