---
title: "Exchange credentials for an access token"
method: POST
path: "/v1/oauth/token"
tags: ["auth"]
---

# Exchange credentials for an access token

`POST /v1/oauth/token`

## Request

- Base URL: `https://api.flowral.app`
- URL: `https://api.flowral.app/v1/oauth/token`
- Auth: none required

Three grants, all `application/x-www-form-urlencoded`:

- `client_credentials` — a workspace credential's id/secret. May also be sent as HTTP Basic.
- `authorization_code` — the code from `/oauth/authorize`, with the PKCE `code_verifier`. Issues a token that acts as the person who signed in, not a workspace credential — plus a `refresh_token`, since a person has no secret to silently re-present an hour later.
- `refresh_token` — trades the refresh token from an `authorization_code` grant for a new access/refresh pair. Rotated: the old refresh token stops working the moment this succeeds. Pass `org_id` to move to a DIFFERENT workspace the same person belongs to, without a second trip through the browser — checked fresh against live membership, same as a new sign-in would be.

Either way the token is a bearer token for this API and nothing else — it is not a planner session and cannot be used against the app.

## Response `200`

SUCCESS

- Token
  - `access_token` string, required
  - `token_type` string, required
  - `expires_in` integer, required: Seconds.
  - `scope` string: Space-separated, and never more than the credential was granted.

## Other responses

- `400`: UNSUPPORTED_GRANT_TYPE · INVALID_SCOPE · invalid_grant · invalid_request
- `401`: INVALID_CLIENT
- `403`: invalid_target

---

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