---
title: "Exchange a code or refresh token for an access token"
method: POST
path: "/oauth/token"
tags: ["MCP OAuth"]
---

# Exchange a code or refresh token for an access token

`POST /oauth/token`

## Request

- Base URL: `https://api.elaichi.ai`
- URL: `https://api.elaichi.ai/oauth/token`
- Auth: none required

Accepts `application/x-www-form-urlencoded` (RFC 6749) or `application/json`. Public clients authenticate with PKCE alone; confidential clients MUST present their secret, by HTTP Basic or `client_secret` in the body. 

`grant_type=authorization_code` requires `code`, `redirect_uri` and `code_verifier`. The redirect URI and the client must match those the code was issued to.

`grant_type=refresh_token` requires `refresh_token`, and rotates it — the presented token is consumed and a new one returned. An optional `scope` may narrow the grant, never widen it; the grant row is the authority, not the copy on the presented token.

Replay is treated as compromise, not as a plain error: presenting an authorization code or a refresh token twice REVOKES THE WHOLE GRANT (OAuth 2.1 §4.1.3 / §6.1), invalidating every token derived from it. The user must re-authorize from `GET /oauth/authorize`. Responses are `Cache-Control: no-store`. Rate limited per `client_id`.

## Request body

- object

## Response `200`

Tokens issued

- object
  - `access_token` string, required: Bearer token for `POST /mcp`. Short-lived; re-check `expires_in` rather than assuming.
  - `token_type` 'Bearer', required
  - `expires_in` integer, required: Access token lifetime in seconds.
  - `refresh_token` string, required: Single-use — rotated on every refresh.
  - `scope` string, required: Space-delimited granted scopes.

## Other responses

- `400`: `invalid_request`, `invalid_grant` (including replay, which also revoked the grant), `invalid_scope`, `invalid_target` or `unsupported_grant_type`.
- `401`: `invalid_client` — unknown client, or client authentication failed.
- `403`: Forbidden
- `404`: Not found
- `429`: Rate limited (`temporarily_unavailable`), with `Retry-After`.

---

[API](https://skmtc.dev/elaichi/apis/elaichi-api.md) · [All operations](https://skmtc.dev/elaichi/apis/elaichi-api/llms.txt) · [OpenAPI document](https://skmtc.dev/elaichi/apis/elaichi-api/revisions/b22cfb7b6d15?raw)
