# Get a token

`POST /oauth/token`

Form body (`application/x-www-form-urlencoded`). `authorization_code`: code + `code_verifier` → a 1-hour access token (`mcp_…`) + a 60-day refresh token (`mcpr_…`). `refresh_token`: every refresh returns a new pair and revokes the old one. A code works once; reusing it revokes the tokens issued from that grant.

## Body

| Field | Type | Description |
|---|---|---|
| `grant_type` (required) | string | Grant type. Values: `authorization_code`, `refresh_token` |
| `code` | string | Authorization code. |
| `redirect_uri` | string | Same as in authorize. |
| `code_verifier` | string | PKCE verifier. |
| `refresh_token` | string | Refresh token. |
| `client_id` (required) | string | Client id. |
| `client_secret` | string | For confidential clients. |

## Response

```json 200
{
  "access_token": "mcp_uBprY6…",
  "expires_in": 3600,
  "refresh_token": "mcpr_AXksm…",
  "scope": "crm.read crm.write",
  "token_type": "Bearer"
}
```
