Getting started
Authentication
Call the REST API with an API key for your own scripts, or OAuth 2.0 for apps that act for a user, such as automation tools, browser extensions or your own app.
API keys
For your own scripts, back-office jobs and integrations. Create a key under Profile > API & MCP tokens. It belongs to you and one workspace, carries the scopes you tick, and works for both the REST API and the MCP server. A key expires after 90 days unless you choose another lifetime (or none) when you create it; you can limit it to IP addresses and revoke it at any time.
curl https://zono.support/api/v1/me \
-H "Authorization: Bearer $ZONO_TOKEN" \
-H "Accept: application/json"OAuth 2.0
For apps that act for a user, such as automation tools, browser extensions or your own app. Zono uses the authorization code flow with PKCE. Public clients (browser, desktop and mobile apps, AI clients) register themselves and must use PKCE with S256; the user picks the workspace and approves the scopes on Zono's consent screen, and the app exchanges the code for tokens.
- Register your app once with its name and redirect URIs. The response carries its
client_id. - Send the user to the authorization URL with a random
stateand a PKCEcode_challenge(the base64url SHA-256 of a randomcode_verifier). - Zono redirects back with a
code. Checkstate, then exchange the code with your verifier. - Call the API with the access token, and refresh it before it expires.
curl -X POST https://zono.support/oauth/register \
-H "Content-Type: application/json" \
-d '{"client_name": "My helpdesk app", "redirect_uris": ["https://app.example.com/oauth/callback"]}'https://zono.support/oauth/authorize
?response_type=code
&client_id=$CLIENT_ID
&redirect_uri=https://app.example.com/oauth/callback
&scope=tickets%3Aread%20tickets%3Awrite
&state=$RANDOM_STATE
&code_challenge=$CODE_CHALLENGE
&code_challenge_method=S256curl -X POST https://zono.support/oauth/token \
-d grant_type=authorization_code \
-d client_id=$CLIENT_ID \
-d redirect_uri=https://app.example.com/oauth/callback \
-d code=$CODE \
-d code_verifier=$CODE_VERIFIER Ask only for the scopes your app needs; users can untick them on the consent screen. Available scopes: tickets:read, tickets:write, customers:read, customers:write, conversations:read, conversations:write, knowledge:read, licenses:read, webhooks:manage. See scopes.
OAuth endpoints
| Endpoint | URL |
|---|---|
| Authorization | GEThttps://zono.support/oauth/authorize |
| Token (code exchange and refresh) | POSThttps://zono.support/oauth/token |
| Dynamic client registration (RFC 7591) | POSThttps://zono.support/oauth/register |
| Revocation (RFC 7009) | POSThttps://zono.support/oauth/revoke |
| Authorization server metadata (RFC 8414) | GEThttps://zono.support/.well-known/oauth-authorization-server |
| Protected resource metadata (RFC 9728) | GEThttps://zono.support/.well-known/oauth-protected-resource |
PKCE: S256 only. Grant types: authorization_code and refresh_token. Client authentication: none, client_secret_post, client_secret_basic (public clients send no secret; first-party integrations send theirs in the body or as HTTP Basic credentials).
Token lifetimes and revocation
- Access tokens last 60 minutes.
- Refresh tokens rotate on every use (store the new one each time) and expire after 180 days unused.
- Authorization codes last 10 minutes and work once.
- Apps disconnect at the revocation endpoint; users disconnect apps under Profile > API & MCP tokens > Connected apps.
- API keys last until they expire or are revoked.
Who the API acts as
Every token acts as the user who created the key or approved the app, in one workspace. An agent's token sees only the tickets that agent sees in the app, and scopes narrow access further, never widen it. A write answers with the full record only to a token that may also read it (otherwise with its id), and licenses name their customer by id unless the token has customers:read.