---
title: "Token endpoint"
method: POST
path: "/api/oauth/token"
tags: ["oauth"]
---

# Token endpoint

`POST /api/oauth/token`

## Request

- Base URL: `https://app.presify.io`
- URL: `https://app.presify.io/api/oauth/token`
- Auth: none declared

Exchanges an authorization code (with PKCE code_verifier) or a refresh token for tokens. Accepts application/x-www-form-urlencoded or application/json. Client authentication: none (public clients), client_secret_basic, or client_secret_post. A Client ID Metadata Document client is public: it sends its document URL as client_id, with no secret. Authorization codes are single-use and live 5 minutes; a code presented twice revokes everything it minted (RFC 9700). Access tokens live 1 hour, refresh tokens rotate and live 30 days. Every OAuth grant ends 90 days after the user approved it, however often its refresh token rotates; refresh then answers invalid_grant and the user approves again. Refresh also answers invalid_grant when the client has been disabled or the user's Microsoft Entra account is disabled or deleted.

## Request body

- TokenRequest: RFC 6749 token request. grant_type selects the shape.
  - `grant_type` 'authorization_code' | 'refresh_token', required
  - `code` string: authorization_code grant.
  - `redirect_uri` string, uri: authorization_code grant; must equal the authorize redirect_uri.
  - `code_verifier` string: authorization_code grant (PKCE).
  - `refresh_token` string: refresh_token grant.
  - `client_id` union: Required unless sent via HTTP Basic. The UUID from dynamic client registration, or the Client ID Metadata Document URL the authorization used.
    - string, uuid: Client registered through dynamic client registration (RFC 7591).
    - string, uri: Client ID Metadata Document URL: https, no port, query or fragment, served from a public host.
  - `client_secret` string: Confidential clients (client_secret_post).
  - `scope` string
  - `resource` string, uri

## Response `200`

Token response (RFC 6749 §5.1).

- TokenResponse
  - `access_token` string, required
  - `token_type` 'Bearer', required
  - `expires_in` integer, required: Seconds (3600).
  - `refresh_token` string: Rotating; the previous refresh token is invalidated.
  - `scope` string, required

## Other responses

- `400`: invalid_request, invalid_grant, invalid_target or unsupported_grant_type.
- `401`: invalid_client: unknown, disabled or mis-authenticated client.

---

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