Every request to a Gozem API must be authenticated. You have two options: a short-lived OAuth2 access token, or a long-lived API key. Use exactly one per request. After a request is authenticated, the platform authorizes it against the services and endpoints your client may call and its IP allowlist.
Caution: Authentication applies to every endpoint. A request without valid credentials is rejected with 401 Unauthorized.
Option 1: OAuth2 access token (recommended)
This is the OAuth2 client credentials flow, meant for backend-to-backend integrations. Your system exchanges its client_id and client_secret for a bearer token, with no user interaction. Use this when you want short-lived credentials and standard token rotation.
Before you start you need a Partner Portal account and an API client with a client_id and client_secret. Both come from the Partner Portal, where you also choose which services and endpoints the client may call.
Request a token from the auth server. The token endpoint is hosted on Gozem’s dedicated auth host — sandbox-auth.gozem.co in sandbox and auth.gozem.co in production — separate from the /{service}/v1 API services:
curl -X POST https://sandbox-auth.gozem.co/oauth2/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials",
"client_id": "CLT_a1b2c3d4e5",
"client_secret": "YOUR_CLIENT_SECRET"
}'
The response carries the token and its lifetime:
{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Imt2MSJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"created_at": "2026-01-15T10:00:00.000Z"
}
Send the token as a bearer header on every API call:
curl https://sandbox-api.gozem.co/{service}/v1/... \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Imt2MSJ9..."
The token automatically carries the access assigned to your client in the portal. To change what a token can do, change the client’s access in the portal.
Token caching
Tokens are valid until they expire. Read expires_in (seconds) from the token response and reuse the same token until it is close to expiry, rather than fetching a new one per request. The default lifetime is 3600 seconds (60 minutes). Caching the token keeps latency down and avoids unnecessary calls to the auth server.
Common token errors
| Error | Cause |
|---|---|
invalid_client |
Client credentials are incorrect or missing |
invalid_grant |
Wrong grant type; it must be client_credentials |
unauthorized |
Token missing, expired, or invalid |
Option 2: API key
For server-to-server integrations that do not need token rotation, use a long-lived API key instead of fetching tokens. Pass it in the x-api-key header:
curl https://sandbox-api.gozem.co/{service}/v1/... \
-H "x-api-key: YOUR_API_KEY"
Treat the key as an opaque secret. It works only while the client is active, so store it securely and never expose it in client-side code.
Choosing between them
Use the OAuth2 token when you want short-lived credentials, central rotation, and the standard bearer pattern. Use the API key when you run a fixed server-side integration and prefer one long-lived credential with no token exchange step. Either way, send only one credential per request. If both headers are present, the bearer token is used.
Authorization
Authentication proves who you are. Authorization decides what you may do. Once a request is authenticated, the platform runs two checks before any business logic executes.
Endpoint access. A client is authorized only for the services and endpoints selected when it was created, with no implicit access to related routes. Calling an endpoint the client was not granted is rejected.
IP allowlist. A client may be restricted to a set of source IP addresses. When an allowlist is set, requests from any other address are rejected, even if the endpoint access is correct.
Both are configured per client in the portal and applied to every request made with it. Updates take effect for new tokens.
Authentication and authorization failures are consistent across services: a request with missing, expired, or invalid credentials returns 401 with the code unauthenticated, and a request that is authenticated but not permitted returns 403 with the code forbidden. Each service documents its own service-specific codes in its section.