# 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
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
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
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
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
{
  "data": {
    "valid": false,
    "code": "DISABLED",
    "keyId": "key_..."
  }
}
```

## Re-enable a disabled key

```typescript
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
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>
