Authentication
Quantify issues access tokens under /oauth and expects those tokens on /v1 requests as bearer tokens.
OAuth summary
Section titled “OAuth summary”- Token endpoint:
POST /oauth/token - Revocation endpoint:
POST /oauth/revoke - Content type:
application/x-www-form-urlencoded - Client authentication: HTTP Basic auth or form
client_idplusclient_secret - Do not send both client-authentication methods in the same request
Available scopes
Section titled “Available scopes”| Scope | Description |
|---|---|
issues:read | Read issues, comments, activity, links, attachments, and agent threads |
issues:write | Create and update issues, comments, agent messages, and links |
projects:read | Read projects and project links |
projects:write | Create and update projects and project links |
members:read | Read workspace members |
teams:read | Read teams and configured SCM repository context |
workspace:read | Read workspace metadata and issue catalogs |
POST /oauth/token
Section titled “POST /oauth/token”Issues an access token.
Supported grant types
Section titled “Supported grant types”| Grant type | Notes |
|---|---|
client_credentials | Supports optional scope |
authorization_code | Requires code and redirect_uri; rejects scope |
refresh_token | Requires refresh_token; supports optional scope |
Form fields
Section titled “Form fields”| Field | Used by | Required | Notes |
|---|---|---|---|
grant_type | all | yes | client_credentials, authorization_code, or refresh_token |
scope | client credentials, refresh token | no | Space-delimited scopes |
code | authorization code | yes | Authorization code to exchange |
redirect_uri | authorization code | yes | Must match the authorization flow |
code_verifier | authorization code | no | PKCE verifier |
refresh_token | refresh token | yes | Refresh token to exchange |
client_id | all | yes if not using Basic auth | Client identifier |
client_secret | all | yes if not using Basic auth | Client secret |
Client credentials example
Section titled “Client credentials example”curl -X POST "$API_BASE_URL/oauth/token" \ -H "Authorization: Basic $(printf '%s:%s' "$CLIENT_ID" "$CLIENT_SECRET" | base64)" \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "grant_type=client_credentials" \ --data-urlencode "scope=issues:read projects:read teams:read"Response 200 OK:
{ "access_token": "<access-token>", "token_type": "Bearer", "expires_in": 3600, "scope": "issues:read projects:read teams:read"}Authorization code example
Section titled “Authorization code example”curl -X POST "$API_BASE_URL/oauth/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "grant_type=authorization_code" \ --data-urlencode "client_id=$CLIENT_ID" \ --data-urlencode "client_secret=$CLIENT_SECRET" \ --data-urlencode "code=<authorization-code>" \ --data-urlencode "redirect_uri=https://app.example.com/oauth/callback" \ --data-urlencode "code_verifier=<pkce-verifier>"Response 200 OK:
{ "access_token": "<access-token>", "token_type": "Bearer", "expires_in": 3600, "scope": "issues:read issues:write", "refresh_token": "<refresh-token>"}Refresh token example
Section titled “Refresh token example”curl -X POST "$API_BASE_URL/oauth/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "grant_type=refresh_token" \ --data-urlencode "client_id=$CLIENT_ID" \ --data-urlencode "client_secret=$CLIENT_SECRET" \ --data-urlencode "refresh_token=<refresh-token>" \ --data-urlencode "scope=issues:read issues:write"Response 200 OK:
{ "access_token": "<access-token>", "token_type": "Bearer", "expires_in": 3600, "scope": "issues:read issues:write", "refresh_token": "<refresh-token>"}Token response notes
Section titled “Token response notes”- Responses send
Cache-Control: no-store - Responses send
Pragma: no-cache refresh_tokenis omitted when not applicableauthorization_coderequests must not includescope
OAuth token errors
Section titled “OAuth token errors”| Status | error | Meaning |
|---|---|---|
400 | invalid_request | Missing or malformed form input |
400 | invalid_scope | Requested scope is invalid or not allowed |
400 | invalid_grant | Authorization code or refresh token is invalid, expired, or unusable |
400 | unsupported_grant_type | Unknown grant type |
401 | invalid_client | Client authentication failed |
429 | temporarily_unavailable | OAuth rate limit exceeded |
503 | temporarily_unavailable | OAuth service temporarily unavailable |
Example:
{ "error": "invalid_client", "error_description": "Client authentication failed."}POST /oauth/revoke
Section titled “POST /oauth/revoke”Revokes an access token or refresh token.
Form fields
Section titled “Form fields”| Field | Required | Notes |
|---|---|---|
token | yes | Token to revoke |
token_type_hint | no | Optional hint such as access_token or refresh_token |
client_id | yes if not using Basic auth | Client identifier |
client_secret | yes if not using Basic auth | Client secret |
Example
Section titled “Example”curl -X POST "$API_BASE_URL/oauth/revoke" \ -H "Authorization: Basic $(printf '%s:%s' "$CLIENT_ID" "$CLIENT_SECRET" | base64)" \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "token=<refresh-token>" \ --data-urlencode "token_type_hint=refresh_token"Response 200 OK with no body.
Using the access token on /v1
Section titled “Using the access token on /v1”curl "$API_BASE_URL/v1/workspace" \ -H "Authorization: Bearer $ACCESS_TOKEN"/v1 authentication failures
Section titled “/v1 authentication failures”| Status | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing bearer token |
401 | invalid_token | Invalid or expired token |
403 | insufficient_scope | Token does not include the required scope |
Example missing token:
{ "code": "unauthorized", "message": "A bearer access token is required."}