ZapyFlow/API documentationopenapi.json

Authentication

Every request carries a workspace API key. There is no OAuth client-credentials flow and no username/password endpoint.

Headers

Either header works. Prefer the bearer form.

bash
Authorization: Bearer zfk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# or
x-api-key: zfk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Never call this API from a browser. x-api-key is deliberately absent from our CORS allowlist, so browser calls fail preflight. That is not a bug to work around: a key shipped to a browser is a leaked key.

Key format

Keys start with zfk_ followed by 32 bytes of CSPRNG output in base64url. Only a SHA-256 hash is stored on our side, so we cannot show you the secret again — the value appears exactly once, at creation.

Failure responses

Every rejected credential returns the same body. Missing, malformed, unknown, revoked and expired keys are byte-identical apart from the request id.

json
{
  "error": "UNAUTHORIZED",
  "message": "Invalid or missing credentials",
  "request_id": "req_01J..."
}

This is deliberate. Telling a caller which of those five states applies would let someone enumerate valid keys and detect the exact moment one is revoked. The real reason is recorded in the workspace audit log, where an owner can read it.

What each status means

StatusMeaningWhat to do
401The credential is absent, malformed, unknown, revoked or expired.Check the key; create a new one if it was revoked.
403 FORBIDDENThe key is valid but this capability is never available to keys.Nothing to retry. Personal-account and internal endpoints are permanently closed to keys.
403 INSUFFICIENT_SCOPEThe key is valid but this scope was not granted — or the creator's role no longer has it.Grant the scope, or have an owner create the key.
429Rate limit.Honour Retry-After.

The authority rule

A key's effective permissions are recomputed on every request:

text
effective(key) = scopes(key)
               ∩ capabilities(role of the member who created the key)
               ∩ scopes that keys may ever hold

So demoting a team member immediately narrows every key they created, and no key can hold a capability its creator never had.

Rotation

Create the new key, deploy it, then revoke the old one. Revocation is immediate and permanent — the row is kept, never deleted, so the record of what that key did survives it.