> This page is for API, version 2026-01-01 (Stable) (default).
> For other versions, use one of these documentation indexes:
> - 2026-01-01 (Stable) (default): https://docs.deel.wtf/api/stable/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.deel.wtf/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.deel.wtf/_mcp/server.

# List API tokens

GET https://api.letsdeel.com/rest/api-tokens

Lists your organization's tokens and your own personal tokens, newest first, without their secret values. Use the filters to find tokens that need attention, such as stale, expiring or orphaned ones.

 **Token scopes**: `tokens:read`

 **Beta**: this version requires the `X-Beta: true` request header and its contract may change before it is promoted to stable. It is scheduled to become stable on 2027-02-03.

Reference: https://docs.deel.wtf/api/reference/endpoints/api-tokens/list-api-tokens-v-2026-11-03

## Authentication

- `Authorization` header (bearer token, required) — ## Authentication The Deel API uses bearer tokens to authenticate requests. All API calls must be made over HTTPS — calls over plain HTTP or without authentication will fail. ```curl curl -X GET 'https://api.deel.training/rest/v2/contracts' \ -H 'Authorization: Bearer YOUR-TOKEN-HERE' ``` [Learn more about authentication](/api/authentication)
- `Authorization` header (bearer token, required) — Standard OAuth2 security scheme based on https://swagger.io/docs/specification/authentication/

## Servers

- `https://api.letsdeel.com/rest` (Production, default)
- `https://api-staging.letsdeel.com/rest` (Demo)

## Request

### Query parameters

- `limit` (integer, optional) — Maximum number of tokens to return in one page, newest first. Defaults to 100.
- `cursor` (string, optional) — Cursor from the previous page. A cursor carries the filters of the first page, so other filters sent with it are ignored.
- `token_type` (enum, optional) — Only return tokens of this type.
  - Allowed values: `PERSONAL`, `ORGANIZATION`
- `signal` (enum, optional) — Only return tokens that need attention for this reason: `FULL_ACCESS` holds every available scope, `STALE` is unused for a while, `EXPIRING` expires soon, `ORPHANED` belongs to someone who left, `PERSONAL` is a usable personal token, `ACTIVE` is any usable token, `INVALIDATED` was invalidated or has expired.
  - Allowed values: `ACTIVE`, `FULL_ACCESS`, `STALE`, `EXPIRING`, `ORPHANED`, `PERSONAL`, `INVALIDATED`
- `search` (string, optional) — Case-insensitive match on the token label, one of its scopes, or its owner's name or email.
- `owner_profile_id` (string, optional) — Only return tokens owned by this profile.
- `sort` (enum, optional) — Sort order. Defaults to newest first.
  - Allowed values: `NEWEST`, `NAME`, `RECENT`, `SCOPES`, `RISK`

### Headers

- `X-Beta` (enum, required, default: true) — Opts in to the beta version of this endpoint. Must be `true`.
  - Allowed values: `true`

## Response

### 200

A page of API tokens.

- `data` (list of ApiTokensGetResponsesContentApplicationJsonSchemaDataItems, required) — The API tokens.
- `has_more` (boolean, required) — True when there is another page after this one.
- `next_cursor` (string, required, nullable) — Cursor for the next page; null when there are no more results.
- `total_count` (integer, required, nullable) — Tokens matching the filters across all pages; null on pages fetched with a cursor.

## Errors

### 400 Bad Request Error

Bad Request. A parameter is missing or invalid.

- `errors` (list of ApiTokensGetResponsesContentApplicationJsonSchemaErrorsItems, required) — The list of errors that caused the request to fail.

### 401 Unauthorized Error

Unauthorized. Authentication credentials were missing or invalid.

- `errors` (list of ApiTokensGetResponsesContentApplicationJsonSchemaErrorsItems, required) — The list of errors that caused the request to fail.

### 403 Forbidden Error

Forbidden. The caller cannot manage the Developer Center, or the token lacks the required scope.

- `errors` (list of ApiTokensGetResponsesContentApplicationJsonSchemaErrorsItems, required) — The list of errors that caused the request to fail.

### 404 Not Found Error

Operation failed.

- `request` (ApiErrorRequest, optional)
- `errors` (list of ApiError, optional)

### 429 Too Many Requests Error

Too Many Requests. The rate limit has been exceeded.

- `errors` (list of ApiTokensGetResponsesContentApplicationJsonSchemaErrorsItems, required) — The list of errors that caused the request to fail.

### 500 Internal Server Error

Internal Server Error. An unexpected error occurred.

- `errors` (list of ApiTokensGetResponsesContentApplicationJsonSchemaErrorsItems, required) — The list of errors that caused the request to fail.

## Types

### ApiTokensGetResponsesContentApplicationJsonSchemaDataItems

- `id` (string, required) — Unique identifier of the API token.
- `label` (string, required) — Name given to the token when it was created.
- `scopes` (list of string, required) — Scopes the token was granted.
- `status` (enum, required) — Where the token is in its lifecycle. `EXPIRING` means it expires within 14 days.
  - Allowed values: `ACTIVE`, `EXPIRING`, `EXPIRED`, `INVALIDATED`
- `is_stale` (boolean, required) — True when the token is usable but has not been used for 60 days.
- `group_ids` (list of integer, required) — Groups the token is limited to; empty when it is not limited.
- `created_at` (string, required, nullable) — When the token was created.
- `created_by` (ApiTokensGetResponsesContentApplicationJsonSchemaDataItemsCreatedBy, required, nullable) — Who created, or now owns, the token. Null for tokens created before owners were recorded.
- `expires_at` (string, required, nullable) — When the token expires; null when it never expires.
- `token_type` (enum, required) — `PERSONAL` tokens act as the person who created them; `ORGANIZATION` tokens act for the whole organization.
  - Allowed values: `PERSONAL`, `ORGANIZATION`
- `integration` (string, required, nullable) — Integration the token was created for, if any.
- `last_used_at` (string, required, nullable) — When the token last called the API.
- `invalidated_at` (string, required, nullable) — When the token was invalidated.
- `invalidated_by` (ApiTokensGetResponsesContentApplicationJsonSchemaDataItemsInvalidatedBy, required, nullable) — Who invalidated the token. Null unless it was invalidated.
- `invalidation_reason` (string, required, nullable) — Reason given when the token was invalidated.
- `should_hide_pii_data` (boolean, required) — True when responses to this token omit personal data.
- `should_hide_employment_data` (boolean, required) — True when responses to this token omit employment data.

### ApiTokensGetResponsesContentApplicationJsonSchemaErrorsItems

- `code` (string, required) — Machine-readable error code.
- `message` (string, required) — Human-readable description of the error.

### ApiErrorRequest

- `method` (string, optional) — The HTTP method of the failed request
- `url` (string, optional) — The relative URL of the failed request
- `status` (double, optional) — The status code of the response
- `api_req_id` (string, optional) — The request ID of the failed request
- `docs` (string, optional) — A link to the official documentation for the requested endpoint resource
- `source` (string, optional) — The source handler which produced the returned error
- `code` (double, optional) — The code of the source handler which produced the returned error

### ApiError

- `message` (string, optional) — A description of the returned error
- `path` (string, optional) — The JSON path where input validation failed

### ApiTokensGetResponsesContentApplicationJsonSchemaDataItemsCreatedBy

Who created, or now owns, the token. Null for tokens created before owners were recorded.

- `name` (string, required, nullable) — Full name of the person, when known.
- `email` (string, required, nullable) — Email of the person, when known.
- `status` (enum, required) — `LEFT` when the person no longer belongs to the organization.
  - Allowed values: `ACTIVE`, `LEFT`
- `profile_id` (string, required) — Profile id of the person.

### ApiTokensGetResponsesContentApplicationJsonSchemaDataItemsInvalidatedBy

Who invalidated the token. Null unless it was invalidated.

- `name` (string, required, nullable) — Full name of the person, when known.
- `email` (string, required, nullable) — Email of the person, when known.
- `status` (enum, required) — `LEFT` when the person no longer belongs to the organization.
  - Allowed values: `ACTIVE`, `LEFT`
- `profile_id` (string, required) — Profile id of the person.

## Examples

**Response**

```json
{
  "data": [
    {
      "id": "7f0c1b9e-3c3a-4a63-9a43-2d6c1a0e8b51",
      "label": "Payroll sync",
      "scopes": [
        "contracts:read",
        "people:read"
      ],
      "status": "ACTIVE",
      "is_stale": false,
      "group_ids": [],
      "created_at": "2026-09-01T10:00:00.000Z",
      "created_by": {
        "name": "Jane Doe",
        "email": "jane.doe@example.com",
        "status": "ACTIVE",
        "profile_id": "1234567"
      },
      "expires_at": "2027-01-01T00:00:00.000Z",
      "token_type": "ORGANIZATION",
      "integration": "zapier",
      "last_used_at": "2026-10-20T08:15:00.000Z",
      "invalidated_at": "2026-10-21T09:30:00.000Z",
      "invalidated_by": {
        "name": "Jane Doe",
        "email": "jane.doe@example.com",
        "status": "ACTIVE",
        "profile_id": "1234567"
      },
      "invalidation_reason": "Rotated after the vendor migration",
      "should_hide_pii_data": false,
      "should_hide_employment_data": false
    }
  ],
  "has_more": true,
  "next_cursor": "eyJvZmZzZXQiOjUwfQ",
  "total_count": 120
}
```

**SDK Code**

```python
import requests

url = "https://api.letsdeel.com/rest/api-tokens"

querystring = {"cursor":"eyJvZmZzZXQiOjUwfQ","limit":"50","owner_profile_id":"1234567","search":"payroll","signal":"STALE","sort":"NEWEST","token_type":"ORGANIZATION"}

headers = {
    "X-Beta": "true",
    "Authorization": "Bearer <token>"
}

response = requests.get(url, headers=headers, params=querystring)

print(response.json())
```

```javascript
const url = 'https://api.letsdeel.com/rest/api-tokens?cursor=eyJvZmZzZXQiOjUwfQ&limit=50&owner_profile_id=1234567&search=payroll&signal=STALE&sort=NEWEST&token_type=ORGANIZATION';
const options = {method: 'GET', headers: {'X-Beta': 'true', Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.letsdeel.com/rest/api-tokens?cursor=eyJvZmZzZXQiOjUwfQ&limit=50&owner_profile_id=1234567&search=payroll&signal=STALE&sort=NEWEST&token_type=ORGANIZATION"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("X-Beta", "true")
	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.letsdeel.com/rest/api-tokens?cursor=eyJvZmZzZXQiOjUwfQ&limit=50&owner_profile_id=1234567&search=payroll&signal=STALE&sort=NEWEST&token_type=ORGANIZATION")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["X-Beta"] = 'true'
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.letsdeel.com/rest/api-tokens?cursor=eyJvZmZzZXQiOjUwfQ&limit=50&owner_profile_id=1234567&search=payroll&signal=STALE&sort=NEWEST&token_type=ORGANIZATION")
  .header("X-Beta", "true")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.letsdeel.com/rest/api-tokens?cursor=eyJvZmZzZXQiOjUwfQ&limit=50&owner_profile_id=1234567&search=payroll&signal=STALE&sort=NEWEST&token_type=ORGANIZATION', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'X-Beta' => 'true',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.letsdeel.com/rest/api-tokens?cursor=eyJvZmZzZXQiOjUwfQ&limit=50&owner_profile_id=1234567&search=payroll&signal=STALE&sort=NEWEST&token_type=ORGANIZATION");
var request = new RestRequest(Method.GET);
request.AddHeader("X-Beta", "true");
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "X-Beta": "true",
  "Authorization": "Bearer <token>"
]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.letsdeel.com/rest/api-tokens?cursor=eyJvZmZzZXQiOjUwfQ&limit=50&owner_profile_id=1234567&search=payroll&signal=STALE&sort=NEWEST&token_type=ORGANIZATION")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```