# Issue and refresh tokens

Exchanges an authorization code or a refresh token for a new token pair. Server-side only, with Basic authentication.

```http
POST https://larm.sa/oauth/token
```

> **Important:** A refresh token can be used once. Resending an authorization code or refresh token after it succeeded revokes every token for the installation (`TOKEN_REUSE_DETECTED`).

## Request body

| Field | Type | Required | Description |
|---|---|---|---|
| `grant_type` | object | yes | One of: `authorization_code`, `refresh_token`. |
| `code` | string | no |  |
| `redirect_uri` | string (uri) | no |  |
| `code_verifier` | string | no |  |
| `refresh_token` | string | no |  |


## Response

| Field | Type | Required | Description |
|---|---|---|---|
| `access_token` | string | yes | Valid for 900 seconds. |
| `refresh_token` | string | yes | Valid for 30 days, and replaced on every refresh. |
| `token_type` | object | yes |  |
| `expires_in` | object | yes |  |
| `scope` | string | yes | Granted scopes, space-separated. |
| `store_id` | string (uuid) | yes |  |
| `installation_id` | string (uuid) | yes |  |
| `installation_generation` | integer | no |  |
| `grant_revision` | integer | no |  |
| `operation_id` | string (uuid) | no |  |


## Example request

```bash
curl -X POST "https://larm.sa/oauth/token" \
  -u "$CLIENT_ID:$CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "grant_type": "authorization_code", "code": "lar_c_…", "redirect_uri": "https://app.example.com/larm/callback", "code_verifier": "…" }'
```


## Example response (200)

```json
{
  "access_token": "lar_at_Q2mV0hN8sYc1kP4tRw7Xa.4f0jK2…",
  "refresh_token": "lar_rt_Hc8nW1qLp5sVz0bTy3Ue.9aQm…",
  "token_type": "Bearer",
  "expires_in": 900,
  "scope": "products:read orders:read",
  "store_id": "5b1d7a62-0c4e-4f38-9a51-2e7b3c9d8f10",
  "installation_id": "c7e4a1f2-6b3d-4e8a-9c05-1d2f3a4b5c6d",
  "installation_generation": 1,
  "grant_revision": 1,
  "operation_id": "0e9d8c7b-6a5f-4e3d-2c1b-0a9f8e7d6c5b"
}
```


## Errors

| HTTP | Code | Meaning |
|---|---|---|
| 401 | `INVALID_CLIENT` | Client authentication failed. |
| 400 | `PKCE_MISMATCH` | code_verifier does not match. |
| 400 | `INVALID_CODE` | The authorization code expired or is invalid. |
| 400 | `REFRESH_ALREADY_USED` | The refresh token was already used. |
| 400 | `TOKEN_REUSE_DETECTED` | Resent after success; tokens were revoked. |
| 409 | `RESULT_UNAVAILABLE_REAUTHORIZE` | The result was lost; recover, then authorize again. |
