Short-lived Bearer tokens for partners that prefer OAuth2 client credentials over sending a long-lived Seller API key on every request. The mint endpoint is additive — scoped API keys remain the recommended default for most integrations.
Who needs this#
Backend teams whose procurement or security policy requires short-lived access tokens, or whose gateway already speaks OAuth2 client credentials.
TL;DR#
- Call
POST /api/seller/oauth/tokenwithgrant_type=client_credentials,client_id(API key UUID), andclient_secret(the plaintext key shown once at creation). - Receive an opaque
avrix_oat_*access token (about one hour TTL). - Use
Authorization: Bearer <access_token>on Seller API v1 routes — same scopes, environment, and IP rules as the underlying key. - Treat
client_secretlike a password. Never log it.
When to use keys vs OAuth tokens#
| Approach | Best for |
|---|---|
| Long-lived API key | Unattended store backends, simple rotation, few moving parts |
| OAuth access token | Gateways that already mint client-credentials tokens; reduced leak window |
You still create the API key in the Console (or via API key management). OAuth does not replace key creation — it exchanges a key for a short-lived Bearer.
Mint a token#
POST /api/seller/oauth/token
Content-Type: application/json
{
"grant_type": "client_credentials",
"client_id": "00000000-0000-0000-0000-000000000000",
"client_secret": "avrix_sk_sbx_your_key_here"
}
| Field | Meaning |
|---|---|
grant_type | Must be client_credentials |
client_id | The API key UUID from the Console (not the secret string) |
client_secret | The plaintext secret shown once at key creation or rotation |
Successful response shape:
{
"access_token": "avrix_oat_…",
"token_type": "Bearer",
"expires_in": 3600,
"meta": { "requestId": "…" }
}
Use the access token on v1 routes:
Authorization: Bearer avrix_oat_…
Lifecycle and enforcement#
- TTL. Tokens expire after about 3600 seconds. Mint a new one before expiry; there is no refresh-token grant.
- Same key rules. Expired keys, revoked companies, non-seller companies, and IP allowlist mismatches fail the same way they would for a raw key Bearer. Mint returns 401 INVALID_CLIENT when credentials are wrong or the key/company is no longer usable.
- Rate limits. The token endpoint throttles by source IP and by
client_id. Expect 429 RATE_LIMIT_EXCEEDED withRetry-Afterwhen you mint too aggressively. - Deployment gate. Some deployments disable token minting. When disabled, the endpoint returns 501 — fall back to the long-lived key Bearer.
Error contract#
The mint endpoint returns the standard flat Avrix error envelope (code, message, requestId),
not the RFC 6749 {"error": "..."} body:
| HTTP | code | RFC 6749 analogue | When |
|---|---|---|---|
| 422 | VALIDATION_FAILED | invalid_request / unsupported_grant_type | Missing field, grant_type other than client_credentials, or client_id not a UUID |
| 401 | INVALID_CLIENT | invalid_client / invalid_grant | Unknown client_id, wrong client_secret, expired/revoked/archived key, or the company is revoked/deleted/not a seller |
| 429 | RATE_LIMIT_EXCEEDED | slow_down | Per-source-IP or per-client_id mint throttle — honour Retry-After |
| 501 | NOT_IMPLEMENTED | — | Token minting is disabled on this deployment — fall back to the key Bearer |
| 503 | SERVICE_UNAVAILABLE | — | Token store unavailable — retry with backoff |
Using an expired or unknown avrix_oat_* token on a v1 route fails like any bad Bearer credential
(401 UNAUTHORIZED).
Security practices#
- Store
client_secretin a secret manager. Never put it in browsers, mobile apps, or public repos. - Prefer minting close to the request path (or in a short-lived worker cache) rather than persisting access tokens across long-running processes.
- Rotate the underlying API key on the same schedule you would without OAuth. Rotating invalidates minting with the old secret; in-flight access tokens expire naturally by TTL.
- Combine with an IP allowlist on the parent key when your egress is stable.
Common mistakes#
- Sending the secret string as
client_id(must be the key UUID). - Logging the mint request body (it contains
client_secret). - Assuming OAuth expands scopes — the access token inherits the key’s scopes exactly.
- Expecting a JWT with readable claims — tokens are opaque
avrix_oat_*strings.
Related#
Token storage#
Access tokens are opaque and stored server-side under their SHA-256 with a one-hour lifetime; the plaintext is never persisted. The same store serves the MCP connector's user tokens, so revoking a connection or a key invalidates every token minted from it at once.