# Exchange a code or a refresh token for tokens

POST`/oauth/token`

Request

**curl**


```bash
curl -X POST "https://api.taskadence.com/oauth/token" \
  --data-urlencode "grant_type=<grant_type>"
```

Response 200

```json
{
  "access_token": "tkd_live_Ab3xQ9eLr0v2Zk5n8WcHt1YpUo4MiGs7Fj6Da-_Bq0R",
  "expires_in": 3600,
  "refresh_token": "tkdr_Zk5n8WcHt1YpUo4MiGs7Fj6Da-_Bq0RAb3xQ9eLr0v2",
  "scope": "tasks:write projects:read",
  "token_type": "Bearer"
}
```

Exchange an authorization code (with its PKCE verifier) or a refresh token for an access token and a new refresh token. Errors are OAuth JSON (`error`, `error_description`). Too many failed exchanges from one app and address: 429 with `Retry-After`.

## Request Bodyrequired

application/x-www-form-urlencoded

_TokenRequest_object

**grant\_type**

required

string

Allowed values: authorization\_code refresh\_token

**code**

Authorization\_code: the code from the redirect

string

**redirect\_uri**

Authorization\_code: exactly the one in the authorization request

string

**code\_verifier**

Authorization\_code: the PKCE verifier (43-128 characters)

string

**refresh\_token**

Refresh\_token: the current refresh token (single use)

string

**scope**

Refresh\_token: optional, narrower scopes (space-separated)

string

**client\_id**

Required for a public app; a confidential app may send it with `client_secret` instead of HTTP Basic

string

**client\_secret**

`client_secret_post` (or use HTTP Basic)

string

## Responses

### 200

Successful Response

application/json

_TokenResponse_

Returned by `oauth.token`.

object

**access\_token**

required

_Access Token_

A Taskadence access token (`tkd_live_…`), 1 hour

string

**token\_type**

_Token Type_

string

default: Bearer

Allowed value: Bearer

**expires\_in**

required

_Expires In_

Seconds

integer

**refresh\_token**

required

_Refresh Token_

`tkdr_…` - single use: each refresh returns a new one

string

**scope**

required

_Scope_

Space-separated scopes this access token holds

string

Example

```json
{
  "access_token": "tkd_live_Ab3xQ9eLr0v2Zk5n8WcHt1YpUo4MiGs7Fj6Da-_Bq0R",
  "expires_in": 3600,
  "refresh_token": "tkdr_Zk5n8WcHt1YpUo4MiGs7Fj6Da-_Bq0RAb3xQ9eLr0v2",
  "scope": "tasks:write projects:read",
  "token_type": "Bearer"
}
```

### 400

An OAuth error (`invalid_request`, `invalid_grant`, `invalid_scope`, `unsupported_grant_type`)

application/json

_OAuthErrorBody_

A `OAuthErrorBody` object.

object

**error**

required

_Error_

Invalid\_request · invalid\_client · invalid\_grant · unauthorized\_client · unsupported\_grant\_type · invalid\_scope

string

**error\_description**

Any of:

**string**


string

**null**


null

Example

```json
{
  "error": "invalid_grant",
  "error_description": "string"
}
```

### 401

Client authentication failed (`invalid_client`)

application/json

_OAuthErrorBody_

A `OAuthErrorBody` object.

object

**error**

required

_Error_

Invalid\_request · invalid\_client · invalid\_grant · unauthorized\_client · unsupported\_grant\_type · invalid\_scope

string

**error\_description**

Any of:

**string**


string

**null**


null

Example

```json
{
  "error": "invalid_grant",
  "error_description": "string"
}
```

### 429

Too many failed token requests from this app and address; wait `Retry-After` seconds

application/problem+json

_Problem_

An RFC 9457 problem details object - the body of every error response. `detail` is the human-readable explanation; `request_id` identifies the request for support.

object

**type**

required

`about:blank` or a `urn:taskadence:problem:*` identifier

string

Allowed values: about:blank urn:taskadence:problem:validation urn:taskadence:problem:invalid-parameter urn:taskadence:problem:precondition-failed urn:taskadence:problem:idempotency-key-reused urn:taskadence:problem:idempotency-key-in-flight urn:taskadence:problem:idempotency-key-invalid urn:taskadence:problem:rate-limit urn:taskadence:problem:internal urn:taskadence:problem:token-invalid urn:taskadence:problem:token-expired urn:taskadence:problem:token-revoked urn:taskadence:problem:insufficient-scope urn:taskadence:problem:test-token-read-only urn:taskadence:problem:token-policy urn:taskadence:problem:url-refused urn:taskadence:problem:mfa-required urn:taskadence:problem:email-unverified urn:taskadence:problem:upload-too-large urn:taskadence:problem:upload-type-not-allowed urn:taskadence:problem:upload-type-mismatch urn:taskadence:problem:upload-rejected

**title**

required

string

**status**

required

integer

**detail**

required

Human-readable explanation (a string; for a 422, the list of validation errors)

**instance**

required

string

**request\_id**

required

string

**errors**

Structured failures: validation errors, or `{loc, msg, allowed}` for a bad parameter

Array<object>

object

**mfa**

On an `mfa-required` problem only: `enrolled` (does the person have an authenticator app set up), `required_for` (`all` or `admins`) and `reason` (`org_policy`: the organization’s requirement; `step_up`: this action needs a second step)

object

**enrolled**

boolean

**required\_for**

string

Allowed values: all admins

**reason**

string

Allowed values: org\_policy step\_up

Example

```json
{
  "type": "about:blank",
  "title": "Forbidden",
  "status": 403,
  "detail": "This task is restricted to other users",
  "instance": "/v1/tasks/T123",
  "request_id": "9b2f1c1e-8c1a-4a53-9f9e-0f5f1f2d7c11",
  "errors": [
    {}
  ],
  "mfa": {
    "enrolled": false,
    "required_for": "all",
    "reason": "org_policy"
  }
}
```

---
Source: https://docs.taskadence.com/reference/operations/oauthtoken/
