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

# Manage API tokens programmatically

> Create, list, update, and revoke API tokens using the API instead of the dashboard. Automate key provisioning and rotation for your integrations.

You can manage the same API tokens available under **Developers > API Tokens** in the dashboard through the `/api/{account_id}/api-tokens` endpoints: create, list, get, update, and delete.

Managing tokens requires the **Developer** permission. Listing and getting tokens need view access; creating, updating, and deleting tokens need edit access.

# Token types

Each API token bundles two credentials:

| Credential            | Prefix     | Use                                                                |
| --------------------- | ---------- | ------------------------------------------------------------------ |
| **Secret token**      | `st_prod_` | Server-side API calls. Sent as `Authorization: Bearer st_prod_...` |
| **Publishable token** | `pt_prod_` | Client-side SDKs. Safe to expose in browser code                   |

Both live and sandbox accounts use the `_prod_` prefix in production. The token record itself is identified by an id with the `tkn_` prefix (e.g., `tkn_prod_a1b2c3d4e5f6g7h8`).

The full **secret token** is only returned once, in the response to the create request. Store it securely — it cannot be retrieved again. Subsequent responses only include `secret_token_preview` (the first 12 characters, e.g. `st_prod_secr...`) for identification.

# Authentication

All requests use your existing secret token:

```bash
curl https://app.paymentkit.com/api/{account_id}/api-tokens \
  -H "Authorization: Bearer st_prod_..."
```

Replace `{account_id}` with your account's external id (e.g., `acc_prod_...`).

# Create a token

Generate a new API token. The response includes the full `secret_token` — this is the only time it is returned, so store it securely.

```bash
curl -X POST https://app.paymentkit.com/api/{account_id}/api-tokens \
  -H "Authorization: Bearer st_prod_..." \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Production key for mobile app",
    "expires_at": "2025-12-31T23:59:59Z"
  }'
```

**Body parameters** (both optional):

| Field         | Type                | Description                                                 |
| ------------- | ------------------- | ----------------------------------------------------------- |
| `description` | string              | Human-readable label for the token                          |
| `expires_at`  | datetime (ISO 8601) | When the token should expire. Omit for a non-expiring token |

**Response** (`ApiTokenWithSecret`):

```json
{
  "id": "tkn_prod_a1b2c3d4e5f6g7h8",
  "description": "Production key for mobile app",
  "secret_token": "st_prod_secret123xyz",
  "secret_token_preview": "st_prod_secr...",
  "publishable_token": "pt_prod_abc123xyz",
  "is_active": true,
  "expires_at": "2025-12-31T23:59:59Z",
  "created_at": "2025-01-15T10:00:00Z",
  "updated_at": "2025-01-15T10:00:00Z"
}
```

# List tokens

Retrieve a paginated list of tokens for the account. The `secret_token` is never included — only `secret_token_preview`.

```bash
curl "https://app.paymentkit.com/api/{account_id}/api-tokens?limit=20" \
  -H "Authorization: Bearer st_prod_..."
```

**Query parameters:**

| Parameter   | Description                                                                                                                                              |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `limit`     | Number of items per page (1–100, default 50)                                                                                                             |
| `offset`    | Number of items to skip (default 0)                                                                                                                      |
| `filter`    | JSON-encoded filter object. Supported fields: `description`, `is_active`, `created_at`, `expires_at`. A `description` value also matches via text search |
| `sortBy`    | Field to sort by: `created_at`, `updated_at`, or `description`                                                                                           |
| `sortOrder` | `1` for ascending, `-1` for descending (default)                                                                                                         |

The response is a paginated envelope: an `items` array of token objects, plus `total` (the total match count) and `has_more`.

# Get a token

Fetch a single token by its `id`. The response is the token object (without the secret token).

```bash
curl https://app.paymentkit.com/api/{account_id}/api-tokens/tkn_prod_a1b2c3d4e5f6g7h8 \
  -H "Authorization: Bearer st_prod_..."
```

A token that does not exist, or that belongs to another account, returns `404`.

# Update a token

Update a token's `description` or toggle its `is_active` status. Only the fields you include in the request body are changed; omitted fields keep their current values. The response is the updated token object (without the secret token).

```bash
curl -X PATCH https://app.paymentkit.com/api/{account_id}/api-tokens/tkn_prod_a1b2c3d4e5f6g7h8 \
  -H "Authorization: Bearer st_prod_..." \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'
```

**Body parameters** (both optional):

| Field         | Type    | Description                                                |
| ------------- | ------- | ---------------------------------------------------------- |
| `description` | string  | Updated label for the token                                |
| `is_active`   | boolean | Set to `false` to deactivate the token without deleting it |

Deactivating a token (`is_active: false`) immediately stops it from authenticating requests — any call using its secret token is rejected with `401` — while keeping the token in your list for audit purposes. Set `is_active: true` to re-enable it.

# Revoke a token

Permanently delete a token. This is a hard delete and cannot be undone.

```bash
curl -X DELETE https://app.paymentkit.com/api/{account_id}/api-tokens/tkn_prod_a1b2c3d4e5f6g7h8 \
  -H "Authorization: Bearer st_prod_..."
```

**Response:**

```json
{ "message": "API token deleted successfully" }
```

To disable a token temporarily instead of deleting it, update it with `is_active: false`. You can re-enable it later by setting `is_active: true`.

# Rotate a token

There is no dedicated rotate endpoint. Rotate a credential by creating a replacement and then retiring the old one:

1. **Create** a new token and deploy its `secret_token` to your integration.
2. Verify the new token works in production.
3. **Deactivate** the old token by sending `PATCH` with `is_active: false` (reversible), or **delete** it (permanent).

Deactivating first and deleting only after a grace period lets you roll back quickly if the new token was misconfigured.

Set an `expires_at` when creating a token to enforce a rotation schedule automatically.

# Next steps

#### [API authentication](/guides/integration)

Review how API keys authenticate requests.

#### [Explore the API](/api-reference)

Browse the full API reference documentation.