Authentication
All requests to api.ziptie.ai require a bearer token in the Authorization
header. A token is one of two kinds. A project token can only access data
for the one project it was created in. A workspace token can access every
project in the workspace it was created in. See token kinds.
Token format
Tokens follow the format zt_live_<43 base64url chars>, total length 51
characters. Example (not a real token):
zt_live_4K8mN2pQrXvYzAbCdEfGhIjKlMnOpQrStUvWxYz0The zt_live_ prefix identifies the token as a live-environment credential.
It is the only prefix the API accepts - a token carrying any other prefix is
rejected with 401 TOKEN_INVALID. There is no sandbox or test environment
today.
Sending the token
Include the token in every request as an HTTP Authorization header:
curl -H "Authorization: Bearer zt_live_<your-token>" \
"https://api.ziptie.ai/v1/projects/PROJECT_ID/prompts"The token is never sent as a query parameter or in the request body.
Token kinds
| Project token | Workspace token | |
|---|---|---|
| Reaches | The one project it was created in | Every project in its workspace, including projects added later. A project moved to another workspace stops being reachable on the next request |
| Created in the app | Project Settings > API & MCP access, by a project role of User or above | Workspace Settings > API & MCP access, by a workspace Owner or Admin |
| Expiry | 30 days, 90 days, 1 year or never | 30 days, 90 days or 1 year. never is not offered |
| Active tokens | Up to 10 per project | Up to 10 per workspace |
| Per-minute limit | 60 | 120 |
| Scopes | read, write, admin |
read, write, admin |
A token carries its kind from creation, and the kind never changes. Both kinds
send the same Authorization: Bearer zt_live_... header, are accepted by every
/v1 operation and every MCP tool, and need the API & MCP access add-on to be
active. Creating a workspace token needs the add-on active at that moment.
Call GET /v1/projects (the MCP tool is list_projects) to list the projects
a token reaches, then pass each id as project_id. A project_id the token
does not reach answers 403 PROJECT_MISMATCH, and so does one that does not
exist. A 503 SERVICE_UNAVAILABLE on a project path can mean the reach check
could not be made at that moment; retry it, because it never means the access
was lost.
A workspace token acts for the workspace, not for a member, so a member's
project roles are not consulted. Mind what that means before you choose a
scope: a write or admin workspace token can change every project in the
workspace. Use read unless the integration writes.
A workspace token works only while its creator is an Owner or Admin of the
workspace. If the creator is demoted below Admin, removed from the workspace
or deactivated, the token stops working on the next request with 401
TOKEN_REVOKED. Before that happens, an Owner or Admin can reassign the token
to themselves in the app: the secret, scope and expiry do not change. When a
workspace Owner hands the workspace over, the transfer dialog offers to move
the tokens they created to the new Owner.
Writes are attributed to the creator. Every write a workspace token makes, in any project, is recorded downstream as made by the person who created, last rotated or was last reassigned the token, not by the person or system that runs the integration.
Scopes
Every token carries exactly one scope. Scopes form a ladder - higher scopes include all permissions of lower scopes:
| Scope | Permissions |
|---|---|
read |
All GET endpoints |
write |
All GET + POST + PATCH endpoints |
admin |
All GET + POST + PATCH + DELETE endpoints |
When you create a token in the ziptie.ai app, you choose its scope. Both token kinds use the same ladder. The scope cannot be changed after creation - revoke the token and create a new one with the desired scope.
Every token created through the app carries at least the read scope. A token
that somehow carries no scope at all is denied on every endpoint with 403
INSUFFICIENT_SCOPE - re-issue it with an explicit scope.
One-time reveal
The full token value is shown exactly once, at creation time. The app stores
only a SHA-256 hash of the token plus a short display identifier derived from
the token's own record ID (shown in the token list as zt_live_ followed by 8
hex characters). No part of the secret itself is kept, so the display
identifier cannot be matched against a token fragment. Copy the token
immediately and store it in a secret manager.
If you lose the token value, revoke it and create a replacement.
Token limits
Each project can have up to 10 active (non-revoked) project tokens, and each workspace up to 10 active workspace tokens. The two caps are separate. Creating an eleventh token of a kind before revoking one returns 409. A workspace token that was rotated counts until its overlap ends.
When the API & MCP access add-on lapses
Turning the add-on off never touches your tokens. They stay in the list, keep their expiry, and are not revoked. What a token can do follows the same subscription rule as the ziptie.ai app:
- Inside the paid period, full access. A subscription that is past due, needs a payment action, is cancelling at the end of its period or is waiting on a payment confirmation keeps every read and every write until its paid period ends.
- Paid period ended, workspace still open: read-only. Every read keeps
working, and every write (
POST,PATCH,DELETEand the matching MCP tools) returns 403SUBSCRIPTION_READ_ONLY.GET /v1/projects/{project_id}reports this state aswrite_access: false, so a client can check before it writes. - Workspace closed, or first payment not yet confirmed: every request
returns 402
PAYMENT_REQUIRED. - Add-on switched off, a trial, or no subscription at all: every request
returns 403
API_ADDON_INACTIVE.
If the subscription check itself cannot be made, the request returns 503
SERVICE_UNAVAILABLE; retry after a short wait.
Turning the add-on off in the app schedules it to end at the end of the current billing period, so tokens keep working until then. Re-enabling it, or undoing the scheduled cancellation, restores the same tokens - nothing has to be re-issued.
The entitlement decision is cached per workspace for 60 seconds. After a billing fix or a re-enable, requests can keep failing for up to a minute. Wait out the minute before concluding a token is broken.
Token lifecycle
- Create in the app: a project token under Project Settings > API & MCP access, a workspace token under Workspace Settings > API & MCP access.
- Use until expiry or until revocation.
- Expire: at the end of the window picked at creation - 30 days, 90 days, or 1 year. Choosing Never creates a project token with no expiry; a workspace token always expires. The window is a fixed set of options; there is no free-form expiry date.
- Revoke: click Revoke in the app. The token stops working immediately. Revocation is permanent.
Token rotation
The safest rotation pattern is create-then-revoke:
- Create a new token.
- Update your application's configuration to use the new token.
- Verify the new token works.
- Revoke the old token.
This avoids a gap where no valid token exists.
For a workspace token the app does the create-then-revoke for you. Rotate creates a successor with the same name, scope and expiry window, and keeps the old secret working for an overlap you pick, 1 hour or 24 hours, so you can update the integration without a gap. The old token's expiry only ever moves earlier. If the old secret may have leaked, choose Compromised instead: the old secret keeps working only until you confirm in the app that you have stored the new one, and for at most 15 minutes. A token that already has a successor cannot be rotated again.
Error responses
Authentication failures return 401 with a JSON body:
{"error": "Invalid API token", "code": "TOKEN_INVALID"}| Code | Cause |
|---|---|
MISSING_AUTH_HEADER |
No Authorization header on the request |
INVALID_AUTH_FORMAT |
Header present but not Bearer zt_live_... format |
TOKEN_INVALID |
Token not found in the database |
TOKEN_REVOKED |
Token was explicitly revoked, or it is a workspace token whose creator is no longer an Owner or Admin of the workspace |
TOKEN_EXPIRED |
Token's expires_at is in the past |
Insufficient scope for a write or delete operation returns 403
INSUFFICIENT_SCOPE. See error codes for the full table.