POST /v1/oauth/token #
The partner’s server-to-server token endpoint: exchange an authorization code, or rotate a refresh token. The client authenticates with client_id + client_secret in the form body or with HTTP Basic.
Headers
Authorizationstring optionalOptional HTTP Basic client authentication:
Basic base64(client_id:client_secret).
Body (JSON)
grant_typestring requiredauthorization_codeorrefresh_token; missing or anything else isunsupported_grant_type.Values:- authorization_code
- refresh_token
codestring optional nullableauthorization_code: the code from the redirect (oc_...).redirect_uristring optional nullableauthorization_code: the sameredirect_urithe code was issued for.code_verifierstring optional nullableauthorization_code: the PKCE verifier (43-128 characters ofA-Z a-z 0-9 - . _ ~) whose S256 challenge was sent to authorize.refresh_tokenstring optional nullablerefresh_token: the latest refresh token (pr_...).client_idstring optional nullableThe app's client id (unless sent with HTTP Basic).
client_secretstring optional nullableThe app's client secret (unless sent with HTTP Basic).
Response data · 200
access_tokenstring requiredAccess token (
pa_...); send it asAuthorization: Bearer <access_token>.token_typestring requiredAlways
Bearer.expires_ininteger (int64) requiredSeconds until the access token expires (86400: one day).
refresh_tokenstring requiredRefresh token (
pr_...), valid for 90 days and single use: every refresh returns a new one. Presenting a used refresh token again revokes the whole connection.scopestring requiredGranted scopes, space separated (OAuth convention), e.g.
read orders.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | invalid_request | Unreadable body or a missing field ( |
| 400 | unsupported_grant_type |
|
| 400 | invalid_grant | The code is invalid, expired or already used, was issued to another client or |
| 401 | invalid_client | No client credentials, an unknown or disabled app, or a wrong secret. |
| 429 | slow_down | Too many failed attempts from this source; retry after |
| 503 | temporarily_unavailable | Partner access is off on this server or its store is temporarily unavailable; retry. |
- Send the body form-encoded (
application/x-www-form-urlencoded, as RFC 6749 specifies) or as JSON. Replies are not the REST envelope: errors are{"error", "error_description"}.
curl -X POST "https://api.cirrus.trade/v1/oauth/token" \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"code": "oc_3zb5bRr1InWe3ipR7EXinezj5kpxNWDpk9piRJNB",
"redirect_uri": "https://partner.example/callback",
"code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
"client_id": "cp_3Oq3YXcuepv3Qx5Z2iC2",
"client_secret": "cps_dG69y0yLbVBxwXqsWbWbrQk1aP0sEuT7mYw2HcN4vZ8LxJfR"
}'import os
import requests
response = requests.post(
"https://api.cirrus.trade/v1/oauth/token",
json={
"grant_type": "authorization_code",
"code": "oc_3zb5bRr1InWe3ipR7EXinezj5kpxNWDpk9piRJNB",
"redirect_uri": "https://partner.example/callback",
"code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
"client_id": "cp_3Oq3YXcuepv3Qx5Z2iC2",
"client_secret": "cps_dG69y0yLbVBxwXqsWbWbrQk1aP0sEuT7mYw2HcN4vZ8LxJfR",
},
timeout=10,
)
print(response.status_code, response.json())const response = await fetch('https://api.cirrus.trade/v1/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
"grant_type": "authorization_code",
"code": "oc_3zb5bRr1InWe3ipR7EXinezj5kpxNWDpk9piRJNB",
"redirect_uri": "https://partner.example/callback",
"code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
"client_id": "cp_3Oq3YXcuepv3Qx5Z2iC2",
"client_secret": "cps_dG69y0yLbVBxwXqsWbWbrQk1aP0sEuT7mYw2HcN4vZ8LxJfR"
}),
});
const body = await response.json();
console.log(response.status, body);{
"access_token": "pa_pyoxfMeCpLKlvksr5Io8XkG7z5ZaKnLz3QEF9m2nuyECcwr2",
"token_type": "Bearer",
"expires_in": 86400,
"refresh_token": "pr_GWiBQeI7nOqJt9PoEovV8T2Nr82NA1jXAJJVHzUG9CFvpK6heN2TmZ76",
"scope": "read orders"
}{
"access_token": "pa_Mn1gAb1cljCkrXUWf3VEAMaGKxmxFx2NoK33lLZ4Zz1nkhI9",
"token_type": "Bearer",
"expires_in": 86400,
"refresh_token": "pr_qKIa3tl8tPdlC9ukkFwGyRgEJJ4GvZbF4YZpj5mbTMm9rNwCRfG3VBAo",
"scope": "read orders"
}{
"error": "invalid_grant",
"error_description": "code is invalid, expired or already used"
}{
"error": "unsupported_grant_type",
"error_description": "unsupported grant_type `password`; use authorization_code or refresh_token"
}{
"error": "invalid_client",
"error_description": "client authentication failed"
}{
"error": "temporarily_unavailable",
"error_description": "storage unavailable: partner access is not enabled"
}