Request parameters
Sent as application/x-www-form-urlencoded in the request body.
| Name | Type | Description |
|---|---|---|
| grant_type required |
string | One of authorization_code, refresh_token, or client_credentials. |
| code conditional |
string | The authorization code returned from /oauth/authorize. Required when grant_type is authorization_code. |
| refresh_token conditional |
string | A previously issued refresh token. Required when grant_type is refresh_token. |
| client_id required |
string | Identifier issued when the client application was registered. |
| client_secret required |
string | Confidential secret for the client. Sent only from a trusted backend, never from a browser or mobile app. |
| redirect_uri conditional |
string | Must match the URI used in the original authorize request. Required for the authorization_code grant. |
| scope optional |
string | Space-separated list of scopes to include in the token. Defaults to the scopes already granted. |
JWT claims issued
The access_token returned is a JWT signed with RS256. Its payload carries:
| Claim | Meaning |
|---|---|
| iss | Issuer — the authorization server's URL. |
| sub | Subject — the user or client the token represents. |
| aud | Audience — the API this token is valid for. |
| scope | Granted scopes, space-separated. |
| iat / exp | Issued-at and expiry, as Unix timestamps. |
| jti | Unique token identifier, used for revocation lookups. |
OpenAPI path definition
This is the exact path object from openapi.yaml — drop it straight into your spec.
/oauth/token: post: summary: Issue an access token operationId: issueToken tags: [Authorization] requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object required: [grant_type, client_id, client_secret] properties: grant_type: type: string enum: [authorization_code, refresh_token, client_credentials] code: { type: string } refresh_token: { type: string } client_id: { type: string } client_secret: { type: string, format: password } redirect_uri: { type: string } scope: { type: string } responses: '200': description: Token issued content: application/json: schema: $ref: '#/components/schemas/TokenResponse' '400': description: Invalid grant or malformed request '401': description: Client authentication failed
curl -X POST https://api.baleduorg.com/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d grant_type=authorization_code \ -d code=AUTH_CODE_FROM_REDIRECT \ -d redirect_uri=https://app.baleduorg.com/callback \ -d client_id=YOUR_CLIENT_ID \ -d client_secret=YOUR_CLIENT_SECRET
const res = await fetch("https://api.baleduorg.com/oauth/token", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "authorization_code",
code: "AUTH_CODE_FROM_REDIRECT",
redirect_uri: "https://app.baleduorg.com/callback",
client_id: "YOUR_CLIENT_ID",
client_secret: "YOUR_CLIENT_SECRET"
})
});
const { access_token, expires_in } = await res.json();
import requests
response = requests.post(
"https://api.baleduorg.com/oauth/token",
data={
"grant_type": "authorization_code",
"code": "AUTH_CODE_FROM_REDIRECT",
"redirect_uri": "https://app.baleduorg.com/callback",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
},
)
token = response.json()["access_token"]
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "rt_8f2c1a...",
"scope": "profile orders:read"
}
{
"error": "invalid_grant",
"error_description": "The authorization code is expired or was already used."
}