> ## Documentation Index
> Fetch the complete documentation index at: https://unkey.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Key Revocation

> Revoke API keys instantly by deleting or disabling them in Unkey. Revoked keys fail verification immediately with no propagation delay.

When a key is compromised or a user's access should end, you can revoke it immediately. Unkey supports both permanent deletion and temporary disabling.

## When to use this

<CardGroup cols={2}>
  <Card title="Security incident" icon="triangle-exclamation">
    Key was leaked in a public repo or logs. Delete it immediately.
  </Card>

  <Card title="User offboarding" icon="user-minus">
    Customer canceled or employee left. Revoke their API access.
  </Card>

  <Card title="Suspicious activity" icon="magnifying-glass">
    Unusual traffic patterns. Disable the key while investigating.
  </Card>

  <Card title="Billing issues" icon="credit-card">
    Payment failed. Temporarily disable until resolved.
  </Card>
</CardGroup>

## Delete vs Disable

| Action      | Effect                            | Reversible? | Use when                            |
| ----------- | --------------------------------- | ----------- | ----------------------------------- |
| **Delete**  | Permanently removes the key       | No          | Key is compromised, user churned    |
| **Disable** | Key exists but can't authenticate | Yes         | Temporary suspension, investigation |

## Delete a key permanently

Use when the key should never work again:

<CodeGroup>
  ```bash cURL theme={"theme":"kanagawa-wave"}
  curl -X POST https://api.unkey.com/v2/keys.deleteKey \
    -H "Authorization: Bearer $UNKEY_ROOT_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "keyId": "key_..."
    }'
  ```

  ```typescript TypeScript theme={"theme":"kanagawa-wave"}
  try {
    const { meta, data } = await unkey.keys.deleteKey({
      keyId: "key_...",
    });
  } catch (err) {
    console.error(err);
    return Response.json({ error: "Internal error" }, { status: 500 });
  }
  ```
</CodeGroup>

The key is invalidated within 60 seconds globally.

<Warning>
  Deletion is permanent. The key cannot be recovered. If you might need to
  restore access, use disable instead.
</Warning>

## Disable a key temporarily

Use when you want to suspend access but may restore it later:

<CodeGroup>
  ```bash cURL theme={"theme":"kanagawa-wave"}
  curl -X POST https://api.unkey.com/v2/keys.updateKey \
    -H "Authorization: Bearer $UNKEY_ROOT_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "keyId": "key_...",
      "enabled": false
    }'
  ```

  ```typescript TypeScript theme={"theme":"kanagawa-wave"}
  try {
    const { meta, data } = await unkey.keys.updateKey({
      keyId: "key_...",
      enabled: false,
    });
  } catch (err) {
    console.error(err);
    return Response.json({ error: "Internal error" }, { status: 500 });
  }
  ```
</CodeGroup>

Verification response when disabled:

```json theme={"theme":"kanagawa-wave"}
{
  "data": {
    "valid": false,
    "code": "DISABLED",
    "keyId": "key_..."
  }
}
```

## Re-enable a disabled key

```typescript theme={"theme":"kanagawa-wave"}
try {
  const { meta, data } = await unkey.keys.updateKey({
    keyId: "key_...",
    enabled: true,
  });
} catch (err) {
  console.error(err);
  return Response.json({ error: "Internal error" }, { status: 500 });
}
```

The key works again immediately.

## Propagation time

* **Delete**: Up to 60 seconds for global invalidation
* **Disable**: Up to 60 seconds for global propagation

For immediate revocation of a compromised key, you may want to also:

1. Rotate any affected secrets downstream
2. Review audit logs for unauthorized access
3. Alert the user if appropriate

## Bulk revocation

To revoke all keys for a specific user, query their keys first:

```typescript theme={"theme":"kanagawa-wave"}
try {
  let cursor: string | undefined;

  // Page through all keys for the user
  do {
    const { data, pagination } = await unkey.apis.listKeys({
      apiId: "api_...",
      externalId: "user_123",
      cursor,
    });

    for (const key of data) {
      await unkey.keys.deleteKey({ keyId: key.keyId });
    }

    cursor = pagination?.hasMore ? pagination.cursor : undefined;
  } while (cursor);
} catch (err) {
  console.error(err);
  return Response.json({ error: "Internal error" }, { status: 500 });
}
```

<Tip>
  For security incidents, consider using [key
  rerolling](/platform/apis/features/rerolling-key) if you need to maintain the
  user's configuration while replacing the compromised key.
</Tip>

## Next steps

<CardGroup cols={2}>
  <Card title="Key rerolling" icon="arrows-rotate" href="/platform/apis/features/rerolling-key">
    Replace a key while preserving its configuration
  </Card>

  <Card title="Audit logs" icon="scroll" href="/audit-log/introduction">
    Track who revoked which keys
  </Card>
</CardGroup>
