Use this flow to get an authorization code from your app and exchange it for an access token you can use in all Zelt API requests.
Warning
Before you start: Make sure you have assigned scopes to your app on the Permissions page. If you skip this, your token will work but all API calls will return empty results.
Step-by-step
-
In Zelt, go to Settings → Security → Developer Hub → Build Apps, open your app and navigate to the App credentials page.
-
Click Code flow. A new browser tab opens and asks for the app's permission.
-
Click Allow access. A new browser tab opens at your configured "Redirect URI".
-
From the browser address bar, copy the value of the
codequery parameter. The URL will look like:https://your-redirect-uri.com/?code=XXXXXXXXXXXXXXXXXXXXXXXX&state=XXXXXXXXXCopy the full value after
code=up to the&. This code expires in 3 minutes. Complete the next step immediately. -
Exchange the authorization code for an access token by sending a
POSTrequest to/apiv2/oauth/authorize/token.Auth type: Basic Auth —
Authorization: Basic base64(CLIENT_ID:CLIENT_SECRET)The
Authorizationheader value must be the Base64 encoding ofCLIENT_ID:CLIENT_SECRET(joined by a literal colon).curl's-uflag handles this automatically. If you are constructing the header manually in code or a tool like Postman, encode it first:echo -n "CLIENT_ID:CLIENT_SECRET" | base64 # → e.g. ZTFiMmMzZDQ6c2VjcmV0Body parameters (form-encoded):
Parameter Type Required Description grant_typestring Yes Must be the literal string authorization_code.codestring Yes The authorization code from step 4. redirect_uristring Yes Must exactly match the URI configured on the App credentials page. Using
curl(recommended):curl -X POST https://go.zelt.app/apiv2/oauth/authorize/token \ -u "CLIENT_ID:CLIENT_SECRET" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=authorization_code" \ -d "code=AUTHORIZATION_CODE_FROM_STEP_4" \ -d "redirect_uri=https://yourapp.example.com/callback"Constructing the header manually (Postman, code, etc.):
ENCODED=$(echo -n "CLIENT_ID:CLIENT_SECRET" | base64) curl -X POST https://go.zelt.app/apiv2/oauth/authorize/token \ -H "Authorization: Basic $ENCODED" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=authorization_code" \ -d "code=AUTHORIZATION_CODE_FROM_STEP_4" \ -d "redirect_uri=https://yourapp.example.com/callback"Warning
Replace
CLIENT_ID,CLIENT_SECRET,AUTHORIZATION_CODE_FROM_STEP_4, andredirect_uriwith your actual values. -
On success, you receive a
200 OKresponse with this structure:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}
access_token: use this in all API requests. It expires afterexpires_inseconds (1 hour).refresh_token: use this to get a new access token without repeating this flow. Store it securely.
- Use the
access_tokenin theAuthorization: Bearerheader for every API call:
curl -X GET "https://go.zelt.app/apiv2/users" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
Common errors
| Error | Cause | Fix |
|---|---|---|
401 Unauthorized on token exchange | Wrong Client ID or Client secret | Copy them again from the App credentials page |
401 Unauthorized on token exchange | Authorization code expired or already used | Restart from step 2. Codes expire after 3 minutes and are single-use |
401 Unauthorized on token exchange | redirect_uri doesn't match what's configured in the app | Use the exact URI from your App credentials page |
401 Unauthorized on token exchange | Authorization header value is not Base64-encoded (e.g. sent as Basic CLIENT_ID:CLIENT_SECRET literally) | The value after Basic must be Base64-encoded. Use curl -u "CLIENT_ID:CLIENT_SECRET" (encodes automatically), or |
encode manually: echo -n "CLIENT_ID:CLIENT_SECRET" | base64 |