---
title: "Exchange a grant for tokens"
url: https://docs.truemarkets.co/api/auth/oauth-token
description: "The token endpoint (RFC 6749 4.1.3 and 6), form encoded."
---

Docs index: https://docs.truemarkets.co/llms.txt

# Exchange a grant for tokens

```
POST https://api.truemarkets.co/v1/auth/oauth/token
```

The token endpoint (RFC 6749 4.1.3 and 6), form encoded.

`authorization_code` consumes the code atomically, checks it was issued
to this client and this `redirect_uri`, and verifies PKCE. A code is
single-use: unknown, expired and already-redeemed are one answer, so a
caller cannot tell them apart.

`refresh_token` rotates: the presented token is consumed and the
response carries its replacement, minted with the stored audience and
scopes, so neither can widen on refresh. Refresh tokens are opaque and
single-use; replaying a consumed one revokes every token descended
from the same grant.

## Responses

Every error status returns the same body, described in [Errors](https://docs.truemarkets.co/developer-resources/errors.md).

### 200

Tokens issued

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `access_token` | string | yes | Audience-bound to the resource named in the authorize request. |
| `token_type` | string, one of `Bearer` | yes |  |
| `expires_in` | integer (int64) | yes | Seconds until the access token expires. |
| `refresh_token` | string | no | Opaque and single-use; each refresh response replaces it. |
| `scope` | string | yes | Space-delimited scopes the grant carries. |

### 400

`invalid_grant` for a bad, expired, replayed or mismatched code or PKCE verifier; `unsupported_grant_type` otherwise.

### 401

The client is unknown or disabled.
