Skip to main content

How authentication works

The Zivio API uses the OAuth 2.0 client credentials grant. Your integration exchanges a client ID and secret for a short-lived access token, then sends that token as a bearer token on every request.
The acting user is carried by the token.

Identifying your organisation

The regional API endpoints (api.zivio.net and its regional variants) serve every Zivio organisation, so each request must say which organisation it is for. Send your Zivio organisation identifier in the zivio-tenant-id header:
This applies to the token request as well as to API calls — the header is read before authentication, so a request without it is rejected before your token is ever examined.
A request to a regional endpoint without a valid zivio-tenant-id returns 404 Tenant Unknown. If your first call fails this way, the header is missing or the identifier is wrong — it is not a problem with your token.
Calling your own Zivio domain instead? If you send requests to your organisation’s own Zivio URL rather than a regional endpoint, the organisation is already identified by the hostname and the zivio-tenant-id header is not required. The regional endpoints are the documented, stable entry points and the ones the API Reference playground uses, so they are the recommended choice for new integrations.

Getting a token

string
required
Must be client_credentials.
string
required
Your application client ID.
string
required
Your application client secret.
string
Space-separated list of scopes, for example projects:read milestones:read invoices:read.
The request is form-encoded, not JSON:
string
The bearer token to send on subsequent requests.
string
Always Bearer.
integer
Token lifetime in seconds.
string
The scopes actually granted — the intersection of what you requested and what your client holds. Always read this rather than assuming you received everything you asked for.

Token lifetime and refresh

Tokens expire — expires_in tells you when. The client credentials grant has no refresh token: when a token expires, request a new one the same way you got the first.
Cache the token for its lifetime rather than fetching one per request, and refresh slightly early so an in-flight request cannot straddle the expiry.

Who am I?

GET /welcome returns the user the token acts as, together with the granted scopes. Call it first in any new integration — it validates the token and tells you what you can do.

Authentication errors

The access token is missing, expired, revoked or malformed. Request a new token; if it still fails, confirm you are sending Authorization: Bearer <token> and not the raw client secret.
The token is valid but was not granted the scope this endpoint requires. The response names both the scope needed and the scopes you hold, so you can widen your token request.
The zivio-tenant-id header is missing or does not match a Zivio organisation. This is checked before authentication, so it is unrelated to your token or scopes. Confirm the identifier with your Zivio administrator.
The token request itself was rejected. Check that the body is form-encoded (application/x-www-form-urlencoded, not JSON), that grant_type is exactly client_credentials, and that the client ID and secret are correct and not URL-escaped twice.

Keeping credentials safe

  • Treat the client secret like a password — environment variables or a secret manager, never source control.
  • Request the narrowest set of scopes that does the job. A read-only integration should never hold a :write scope.
  • Use separate clients for separate integrations so one can be revoked without disrupting the others.