Skip to main content
POST
/
oauth2
/
token
{
  "access_token": "<string>",
  "token_type": "<string>",
  "expires_in": 123,
  "refresh_token": "<string>",
  "scope": "<string>",
  "invalid_request": {},
  "invalid_grant": {},
  "invalid_client": {},
  "unsupported_grant_type": {}
}

Endpoint

POST /oauth2/token

Content Type

application/x-www-form-urlencoded

Grant Types

This endpoint supports two grant types:
  1. authorization_code - Exchange authorization code for tokens
  2. refresh_token - Refresh an expired access token

Authorization Code Grant

Exchange an authorization code for access and refresh tokens.

Request Parameters

grant_type
string
required
Must be authorization_code
code
string
required
The authorization code received from /oauth2/authorize
client_id
string
required
Your agent ID (obtained during registration)
redirect_uri
string
required
Must exactly match the redirect_uri used in authorization request
code_verifier
string
required
The PKCE code verifier (OAuth 2.1 requirement)
client_secret
string
Optional for public clients. Required for confidential clients.

Example Request

curl -X POST https://api.auth-agent.com/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=AUTH_CODE_HERE" \
  -d "client_id=your_agent_id" \
  -d "redirect_uri=http://localhost:3000/callback" \
  -d "code_verifier=PKCE_VERIFIER_HERE"

Success Response

access_token
string
JWT access token for making authenticated API requests
token_type
string
Always Bearer
expires_in
number
Token lifetime in seconds (typically 3600 = 1 hour)
refresh_token
string
Long-lived token for refreshing the access token
scope
string
Space-separated list of granted scopes
Response
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "scope": "openid profile email"
}

Refresh Token Grant

Refresh an expired access token using a refresh token.

Request Parameters

grant_type
string
required
Must be refresh_token
refresh_token
string
required
The refresh token received from a previous token response
client_id
string
required
Your agent ID
client_secret
string
Optional for public clients

Example Request

curl -X POST https://api.auth-agent.com/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=REFRESH_TOKEN_HERE" \
  -d "client_id=your_agent_id"

Success Response

Response
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "openid profile email"
}
Refresh tokens are not rotated by default. The same refresh token can be used multiple times.

Error Responses

invalid_request
400
Missing or invalid required parameters
{
  "error": "invalid_request",
  "error_description": "Missing required parameters: code, client_id, redirect_uri"
}
invalid_grant
401
Invalid authorization code, expired code, or PKCE verification failed
{
  "error": "invalid_grant",
  "error_description": "PKCE verification failed"
}
invalid_client
401
Invalid client_id or client_secret
{
  "error": "invalid_client",
  "error_description": "Client authentication failed"
}
unsupported_grant_type
400
Grant type not supported (OAuth 2.1 only supports authorization_code and refresh_token)
{
  "error": "unsupported_grant_type",
  "error_description": "Only authorization_code and refresh_token grant types are supported"
}

Common Issues

Cause: Code verifier doesn’t match the original code challengeSolutions:
  • Ensure you’re using the same verifier that generated the challenge
  • Check that the verifier is stored correctly in sessionStorage
  • Verify the SHA-256 hashing is implemented correctly
Cause: Code older than 10 minutesSolution: Restart the OAuth flow from /oauth2/authorize
Cause: Redirect URI doesn’t exactly match the one used in authorizationSolution: Ensure exact match including protocol, domain, port, and path
Cause: Refresh token expired (30 days) or revokedSolution: User must re-authenticate via /oauth2/authorize

Token Lifetime

Token TypeLifetimeNotes
Authorization Code10 minutesSingle use only
Access Token1 hourCan be refreshed
Refresh Token30 daysLong-lived

Security Notes

  • Authorization codes are single-use and expire quickly - Always use PKCE (required by OAuth 2.1) - Store refresh tokens securely - Never expose tokens in URLs or logs