
## Revoke a token

`DELETE /v1/infra/servers/:id/access-tokens/:tokenId`

Revokes a token early. New `share-url` visits and `api-bearer` calls are blocked immediately.

A development-team key with a current `ADMIN` or `DEVELOPER` role on this server can revoke only tokens issued by that same key. A token from another key returns `404 NOT_FOUND`.

## Parameters

| Parameter | In | Type | Required | Description |
|----------|---|-----|:-----:|----------|
| `id` | path | string (UUID) | yes | BLACKHOLE server ID. List: [`GET /v1/infra/servers`](/docs/infra/servers/list) |
| `tokenId` | path | string (UUID) | yes | Token ID saved from your own [`POST /access-tokens`](./create.md) response; only the server-managing key can also obtain it through [`GET /access-tokens`](./list.md) |

## Examples

### curl — personal key

```bash
curl -X DELETE \
  -H "X-Api-Key: YOUR_API_KEY" \
  "https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/access-tokens/TOKEN_ID"
```

### curl — OAuth application

```bash
curl -X DELETE \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  "https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/access-tokens/TOKEN_ID"
```

### JavaScript — personal key

```javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/access-tokens/${tokenId}`,
  {
    method: 'DELETE',
    headers: { 'X-Api-Key': 'YOUR_API_KEY' },
  }
)
// 204 No Content — no response body
if (res.status !== 204) {
  const { error } = await res.json()
  throw new Error(error.code)
}
```

### JavaScript — OAuth application

```javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/access-tokens/${tokenId}`,
  {
    method: 'DELETE',
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
    },
  }
)
// 204 No Content — no response body
if (res.status !== 204) {
  const { error } = await res.json()
  throw new Error(error.code)
}
```

## Response

`204 No Content` — no response body. Success is indicated by the response code, not the content.

## Response example

```
HTTP/1.1 204 No Content
```

## Error response example

410 — token already revoked:

```json
{
  "success": false,
  "error": {
    "code": "ALREADY_REVOKED",
    "message": "Token already revoked"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 401 | `MISSING_API_KEY` | No API key was supplied through `X-Api-Key` or a supported `Authorization: Bearer` scheme |
| 401 | `INVALID_API_KEY` | The authentication key is not recognized |
| 401 | `KEY_INACTIVE` | The requesting API key is no longer active |
| 401 | `KEY_EXPIRED` | The requesting API key has expired; this is distinct from resource URL expiry |
| 401 | `NO_PORTAL` | A non-management key has no portal binding |
| 401 | `COWORK_CHAT_KEY_INACTIVE` | The parent device key behind a Cowork chat key is no longer usable |
| 401 | `WRONG_AUTH_SCHEME` | An OAuth application key was sent as a Bearer session: put the key in `X-Api-Key` and the session in `Authorization: Bearer` |
| 401 | `INVALID_SESSION` | The supplied OAuth session is invalid or expired |
| 401 | `TOKEN_EXPIRED` | The OAuth user token expired and its refresh failed; re-authorization is required |
| 401 | `TOKEN_INVALID` | When the partner AI plane is enabled, its supplied token is unknown or expired |
| 401 | `KEY_REVOKED` | The partner credential behind the AI plane token is revoked |
| 402 | `ACCOUNT_FROZEN` | The key owner’s account is frozen. With wallet-debt scoping disabled, the shared API-key guard refuses this call before its handler. Follow error.topupUrl to resolve the balance; this status alone does not authorize repeating a prior write. |
| 403 | `TOKEN_OWNER_MISMATCH` | The server belongs to a different API key. An exception is a development-team key with a current `ADMIN` or `DEVELOPER` role on this server. |
| 403 | `INFRA_FORBIDDEN_FOR_COWORK_KEY` | The call was made with a Cowork key — such a key works with data only and cannot perform write operations. To issue a key that can, see [Project key for deploy](/docs/cowork/deploy-key) |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | A read-only key cannot perform this write. |
| 403 | `EXTERNAL_COLLABORATOR_KEY_OUT_OF_SCOPE` | This operation is outside the external-collaborator key route list. Use the key that manages the server |
| 403 | `PORTAL_COLLABORATOR_KEY_WRONG_SERVER` | The development-team key is bound to another server |
| 403 | `PORTAL_COLLABORATOR_NOT_A_MEMBER` | Development-team membership ended or the current role no longer permits this operation |
| 403 | `IP_NOT_ALLOWED` | The caller IP is outside the key allowlist. |
| 403 | `OWNER_BLOCKED` | The key owner is blocked. |
| 403 | `OWNER_DELETED` | The key owner was deleted. |
| 403 | `PORTAL_SUSPENDED` | The bound portal is suspended. |
| 403 | `PORTAL_DELETED` | The bound portal was deleted. |
| 403 | `PORTAL_BLOCKED` | The bound portal is blocked. |
| 403 | `MANAGEMENT_KEY_NO_ENTITY_ACCESS` | The management key lacks the portal binding or entity authority required by this call. |
| 403 | `AGENT_MAINTENANCE_KEY_OUT_OF_SCOPE` | The maintenance key route list does not include this operation. |
| 403 | `APP_API_KEY_OUT_OF_SCOPE` | The application key route list does not include this operation. |
| 403 | `WAITLIST_PENDING` | The key owner has not been activated. |
| 403 | `SESSION_APP_MISMATCH` | The OAuth session belongs to another application. |
| 403 | `PLANE_FORBIDDEN` | The partner key does not allow this AI plane. |
| 403 | `SYSTEM_FORBIDDEN` | The partner key does not allow this AI system. |
| 403 | `SCOPE_FORBIDDEN` | The partner AI plane forbids this route. |
| 403 | `CONNECT_COMPANY_DERIVED_TOKEN_FORBIDDEN` | A company connection key cannot manage derived tokens. |
| 403 | `COWORK_READONLY` | The Cowork seat is read-only. |
| 403 | `GALAXY_DISABLED` | Galaxy operations are disabled for this portal. |
| 404 | `SERVER_NOT_FOUND` | Server not found or deleted |
| 404 | `NOT_FOUND` | The server's portal has been deactivated; or a token with this ID was not found, belongs to a different server, or was issued by another key when called with a development-team key |
| 410 | `ALREADY_REVOKED` | Token already revoked |
| 409 | `AGENT_WRITE_ALREADY_EXECUTED` | With the agent-write replay guard enabled, this exact DELETE by the runtime agent key already has a claim and was not repeated. `error.firstExecutedAt` is the first claim timestamp; `error.firstStatus` is its HTTP status or `null` while the first attempt is still in flight. Reconcile and report that result; do not automatically repeat an unknown outcome. Failed first attempts release their claims |
| 429 | `QUOTA_EXCEEDED` | API billing is enabled with a nonzero overage price: the daily free quota is exhausted and the PREPAY balance is not positive. Top up the balance. `error.quota` and `error.used` report counts; `X-RateLimit-Quota`, `X-RateLimit-Used` and `X-RateLimit-Remaining` report the quota, usage and zero remainder. This refusal does not promise `Retry-After` or `X-RateLimit-Scope` |
| 429 | `CALLER_RATE_LIMITED` | The shared key or user request limit. Wait for the number of seconds specified in `Retry-After`; `X-RateLimit-Scope` identifies the refusing layer |
| 503 | `FEATURE_DISABLED` | The access-tokens section is disabled on the platform. The pre-call signal and the fallback are described in [Availability](/docs/infra/access-tokens#availability) |
| 503 | `ACCOUNT_PENDING_ERASURE` | The key owner is pending erasure or being erased. Header `Retry-After: 3600`. |
| 503 | `SERVICE_DISABLED` | The partner AI plane or its quota-readiness service is disabled. No `Retry-After` is promised for this refusal. |
| 503 | `user_self_deletion_pending` | The API key owner scheduled self-deletion. The token plugin refuses the call before its handler. Header `Retry-After: 604800`. |

Full list of common API errors — [Errors](/docs/errors).

## Known specifics

- **`share-url` cookies keep working for up to 10 minutes after revocation.** Revocation immediately blocks new visits, but a browser with cookies already set sees the application until the session JWT expires.
- **An expired token can still be revoked.** Revocation looks only at the revoked flag, so a record with an `expiresAt` in the past accepts `DELETE` and returns `204`. Refreshing such a record, by contrast, returns `410 TOKEN_EXPIRED` — [Refresh a token](./refresh.md).

## See also

- [Mint a token](./create.md)
- [List tokens](./list.md)
- [Access tokens](/docs/infra/access-tokens)
