Exchange a code, or refresh a token
No authentication.
Accepts application/x-www-form-urlencoded (the OAuth default) and
JSON. A confidential client authenticates with client_secret_post or
HTTP Basic; a public client sends no secret and is protected by PKCE
alone.
grant_type=authorization_code — send code, redirect_uri,
client_id and code_verifier. The code is single-use and lives five
minutes. A code that never existed, has expired or has already been
redeemed all answer the same invalid_grant.
grant_type=refresh_token — send refresh_token and client_id.
Refresh tokens rotate: the response carries a new one and the presented
token is burnt. Presenting a burnt token is treated as a leak and
revokes every token of that login. scope may be sent to narrow the new
token; it can never widen.
A refresh_token is only issued when the offline_access scope was
granted. Rate limited to 60 requests per minute per IP and 600 per
minute per client_id.
Request body
Content type: application/x-www-form-urlencoded · required
- grant_typestringrequiredOne of:
"authorization_code""refresh_token" - client_idstringrequired
- client_secretstring
Confidential clients only, and only when not using HTTP Basic. A public client never sends one.
- codestring
authorization_codeonly — the value from the redirect. - redirect_uristring
authorization_codeonly — must equal the one the code was issued for. - code_verifierstring
authorization_codeonly. The PKCE verifier, 43–128 characters from[A-Za-z0-9._~-], whose SHA-256 produced thecode_challenge. - refresh_tokenstring
refresh_tokenonly. - scopestring
refresh_tokenonly, and optional: narrows the new token. It can never widen — asking for more than was granted isinvalid_scope.
Content type: application/json · required
- grant_typestringrequiredOne of:
"authorization_code""refresh_token" - client_idstringrequired
- client_secretstring
Confidential clients only, and only when not using HTTP Basic. A public client never sends one.
- codestring
authorization_codeonly — the value from the redirect. - redirect_uristring
authorization_codeonly — must equal the one the code was issued for. - code_verifierstring
authorization_codeonly. The PKCE verifier, 43–128 characters from[A-Za-z0-9._~-], whose SHA-256 produced thecode_challenge. - refresh_tokenstring
refresh_tokenonly. - scopestring
refresh_tokenonly, and optional: narrows the new token. It can never widen — asking for more than was granted isinvalid_scope.
Responses
200A fresh token set.
Content type: application/json
- access_tokenstring
RS256 JWT. Verify it against the JWKS.
- token_typestringOne of:
"Bearer" - expires_ininteger
Access token lifetime in seconds.
- refresh_tokenstring
Present only when
offline_accesswas granted. - id_tokenstring
RS256 JWT carrying the identity claims the scopes allow.
- scopestring
The scopes actually granted, space-separated.
{
"access_token": "string",
"token_type": "Bearer",
"expires_in": 0,
"refresh_token": "string",
"id_token": "string",
"scope": "string"
}400invalid_request, unsupported_grant_type, invalid_grant
(unknown, expired, already-used or mismatched code or refresh
token — deliberately indistinguishable), invalid_scope, or
unauthorized_client for a client that has been switched off.
Content type: application/json
- errorstringrequired
The machine-readable code.
- error_descriptionstring
A human-readable explanation. Never match on this.
{
"error": "invalid_grant",
"error_description": "authorization code is invalid or expired"
}401invalid_client — the client id is unknown or the secret is wrong.
Carries WWW-Authenticate: Basic when Basic auth was attempted.
Content type: application/json
- errorstringrequired
The machine-readable code.
- error_descriptionstring
A human-readable explanation. Never match on this.
{
"error": "invalid_grant",
"error_description": "authorization code is invalid or expired"
}429Too many token requests.
Content type: application/json
- errorstringrequired
Human-readable description of what went wrong.
{
"error": "slow_down"
}Example request
curl -X POST "https://api.nsin.ir/oauth/token" \
-H "Authorization: Bearer $NSIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"client_id": "string",
"client_secret": "string",
"code": "string",
"redirect_uri": "string",
"code_verifier": "string",
"refresh_token": "string",
"scope": "string"
}'