---
title: "Exchange a grant for OAuth tokens"
method: POST
path: "/oauth/token"
---

# Exchange a grant for OAuth tokens

`POST /oauth/token`

Issues an access token and a refresh token in exchange for a valid grant.
Three grant types are supported: `"authorization_code"`, `"refresh_token"`,
and `"urn:ietf:params:oauth:grant-type:device_code"`.

For `"authorization_code"` grants, supply `code`, `client`, `redirect_uri`, and
optionally `code_verifier` for PKCE flows. Each authorization code is single-use;
consuming it a second time returns `invalid_grant`.

For `"refresh_token"` grants, supply `refresh_token`. The endpoint rotates the
refresh token on every call and returns a fresh pair of tokens.

For device-code grants, supply `device_code` and `client`. Poll this endpoint
after receiving `authorization_pending` until the user approves or the code
expires. Slow down polling if you receive `slow_down`.

This endpoint is rate-limited to 20 requests per IP per 60 seconds. Exceeding
the limit returns HTTP 429 with `"error": "too_many_requests"`.

## Request body

- object
  - `client` string — OAuth client ID identifying the application requesting tokens. Required for `"authorization_code"` and device-code grants.
  - `code` string — Single-use authorization code issued by the authorization endpoint. Required for `"authorization_code"` grants.
  - `code_verifier` string — PKCE code verifier corresponding to the `code_challenge` sent in the authorization request. Required when the authorization code was issued with a code challenge; omit otherwise.
  - `device_code` string — Device code received from the device authorization endpoint. Required for device-code grants.
  - `grant_type` string, required — The OAuth 2.0 grant type. One of `"authorization_code"`, `"refresh_token"`, or `"urn:ietf:params:oauth:grant-type:device_code"`.
  - `redirect_uri` string — Redirect URI that was used in the original authorization request. Must exactly match the URI on record for the client. Required for `"authorization_code"` grants.
  - `refresh_token` string — Refresh token received from a previous token response. Required for `"refresh_token"` grants. The token is rotated on each successful call.

## Response `200`

Successful response

- OAuthTokenResponse — A successful OAuth 2.0 token response. Issued by the token endpoint after a completed authorization or device-flow grant.
  - `access_token` string, required — Bearer token used to authenticate API requests. Include this value in the `Authorization: Bearer <token>` header.
  - `expires_in` integer, required — Number of seconds until the access token expires.
  - `refresh_token` string — Token that can be exchanged for a new access token once the current one expires. `null` if the grant type does not issue refresh tokens.
  - `scope` string — Space-separated list of scopes granted to the access token. `null` if scope was not included in the grant request.
  - `token_type` string, required — Token type. Always `"Bearer"`.
  - `user` User — A platform user account. Represents a human or system actor that can own threads, belong to an organization, and interact with the API.
    - `alias` string — Short handle or alias for the user. `null` if not set.
    - `app` string — ID of the app this user (and their access token) is scoped to (`dap_...`). `null` if the user is not scoped to an app.
    - `app_name` string — Display name of the user's app. `null` when the app association was not preloaded by the caller.
    - `email` string — Email address of the user.
    - `id` string, required — User ID (`usr_...`).
    - `is_system_user` boolean — `true` if this account is an internal system user rather than a human. System users are created automatically by the platform.
    - `metadata` object — Arbitrary key-value metadata attached to the user. Defaults to an empty object.
    - `name` string — Full display name of the user. `null` if the user has not set a name.
    - `org` string — ID of the organization this user belongs to (`org_...`). `null` if the user is not a member of any organization.
    - `org_name` string — Display name of the user's organization. `null` when the user is not in an org, or when the org association was not preloaded by the caller.
    - `org_role` string — Role of the user within their organization. One of `"admin"`, `"member"`, or `"viewer"`. `null` when the user is not a member of any organization.
    - `sandbox` string — ID of the sandbox environment this user is scoped to (`sbx_...`). `null` for production users.
    - `sandbox_name` string — Display name of the user's sandbox environment. `null` for production users, or when the sandbox association was not preloaded by the caller.

## Other responses

- `400` — Bad request
- `401` — Unauthorized
- `429` — Rate limited

---

[API](https://skmtc.net/archastro/apis/archastro-platform-api.md) · [All operations](https://skmtc.net/archastro/apis/archastro-platform-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/archastro/archastro-platform-api/revisions/a8772b442f86/schema)
