Avnology ID
API ReferenceOAuth 2.1 / OIDC

Token Endpoint

Exchange an authorization code for tokens, refresh an access token, or obtain tokens via client credentials.

Endpoint

POST /oauth2/token

Base URL: https://api-id.avnology.net

Content-Type: application/x-www-form-urlencoded

The token endpoint supports three grant types:

  • Authorization code -- exchange a code for access + refresh + ID tokens
  • Refresh token -- obtain a new access token using a refresh token
  • Client credentials -- machine-to-machine authentication

Authorization Code Exchange

Request

ParameterTypeRequiredDescription
grant_typestringYesauthorization_code
codestringYesAuthorization code from the callback
redirect_uristringYesMust match the original request
client_idstringYesYour client ID
client_secretstringConfidential clientsYour client secret
code_verifierstringYesThe PKCE code verifier from the authorization request

Response (200 OK)

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9.eyJpc3MiOiJodHRwczovL29hdXRoLmlkLmF2bm9sb2d5LmNvbSIsInN1YiI6InVzcl80ZjE4YWNlYy0yNzEyLTRiZTctYTlhZi1iMDYzYjRmNmRlYmEiLCJhdWQiOiJjbGlfYWJjMTIzZGVmNDU2IiwiZXhwIjoxNzEyNTgzMzAwLCJpYXQiOjE3MTI1ODI0MDAsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJvcmdfaWQiOiJvcmdfN2EyYjNjNGQiLCJvcmdfbmFtZSI6IkFjbWUgQ29ycCJ9.signature",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "rt_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6",
  "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL29hdXRoLmlkLmF2bm9sb2d5LmNvbSIsInN1YiI6InVzcl80ZjE4YWNlYy0yNzEyLTRiZTctYTlhZi1iMDYzYjRmNmRlYmEiLCJhdWQiOiJjbGlfYWJjMTIzZGVmNDU2IiwiZXhwIjoxNzEyNTgzMzAwLCJpYXQiOjE3MTI1ODI0MDAsImVtYWlsIjoiamFuZUBhY21lLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoiSmFuZSBTbWl0aCJ9.signature",
  "scope": "openid profile email"

Refresh Token

Request

curl -X POST https://api-id.avnology.net/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=rt_a1b2c3d4e5f6g7h8..." \
  -d "client_id=cli_abc123def456" \
  -d "client_secret=cs_secret_value"
ParameterTypeRequiredDescription
grant_typestringYesrefresh_token
refresh_tokenstringYesThe refresh token
client_idstringYesYour client ID
client_secretstringConfidential clientsYour client secret
scopestringNoRequest a subset of the original scopes

Response (200 OK)

{
  "access_token": "eyJhbGciOiJSUzI1NiI...",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "rt_new_token_value...",
  "scope": "openid profile email"
}

Refresh tokens are rotated on each use. The old refresh token is invalidated and a new one is returned.

Client Credentials

For machine-to-machine (M2M) authentication without a user:

Request

curl -X POST https://api-id.avnology.net/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=cli_abc123def456" \
  -d "client_secret=cs_secret_value" \
  -d "scope=admin:users:read admin:orgs:read"

Response (200 OK)

{
  "access_token": "eyJhbGciOiJSUzI1NiI...",
  "token_type": "Bearer",
  "expires_in": 900,
  "scope": "admin:users:read admin:orgs:read"
}

No refresh token is issued for client credentials grants.

Errors

ErrorHTTPDescription
invalid_request400Missing or invalid parameter
invalid_client401Client authentication failed
invalid_grant400Code expired, already used, or verifier mismatch
unauthorized_client400Client not authorized for this grant type
unsupported_grant_type400Grant type not supported
invalid_scope400Requested scope is invalid
{
  "error": "invalid_grant",
  "error_description": "The authorization code has expired or has already been used"
}

Code Examples

JavaScript (fetch)

async function exchangeCode(code, codeVerifier, redirectUri, clientId, clientSecret) {
  const response = await fetch('https://api-id.avnology.net/oauth2/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded'










Python (httpx)

import httpx

def exchange_code(code: str, code_verifier: str, redirect_uri: str, client_id: str, client_secret: str) -> dict:
    return httpx.post(
        "https://api-id.avnology.net/oauth2/token"








Go (net/http)

func exchangeCode(ctx context.Context, code, codeVerifier, redirectURI, clientID, clientSecret string) (*TokenResponse