---
title: "Exchange a credential for an access token"
method: POST
path: "/oauth/token"
tags: ["Authentication"]
---

# Exchange a credential for an access token

`POST /oauth/token`

## Request

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

The OAuth 2.0 token endpoint. `grant_type` picks the exchange:

- `client_credentials` (RFC 6749 section 4.4): authenticate as a service account, its id as `client_id` and one of its keys as `client_secret`, in the form body or as HTTP Basic credentials. The token is a signed JWT that lasts 60 minutes and carries every scope unless `scope` narrows it. Disabling or revoking the key, or disabling the service account, ends its tokens.
- `urn:ietf:params:oauth:grant-type:device_code` (RFC 8628 section 3.4): a native client polling for the device login it started, with `device_code` and its `client_id`. Answers `authorization_pending` until the person approves, `slow_down` when polled sooner than the interval, then the token set, once.
- `refresh_token`: a native client renewing the tokens a device login gave it, with `refresh_token` and its `client_id`. The refresh token is replaced on every use.

## Response `200`

Successful Response

- TokenResponse
  - `access_token` string, required: A signed JWT access token, sent as `Authorization: Bearer <token>`. Treat it as opaque.
  - `token_type` string, required: Always `Bearer`.
  - `expires_in` integer, required: Seconds until the token expires.
  - `scope` string, nullable: The space-delimited scopes the token carries.
  - `refresh_token` string, nullable: Device and refresh grants only: the refresh token, replaced on every refresh.

## Other responses

- `400`: An OAuth 2.0 error
- `401`: Client authentication failed
- `422`: Validation Error

## Changes

- **2026-10-19** `0581965f4bc0`: 2 breaking, 3 info
  - the response property `scope` became optional for the status `200`
  - response property `scope` list-of-types was widened by adding types `null` to media type `application/json` of response `200`
  - added the new optional request property `device_code`
  - added the new optional request property `refresh_token`
  - …1 more
- **2026-10-11** `2d86d473cda6`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/layer/apis/layer-rest-api/changes/oauth/token/post.md)

---

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