# Revoke

Throw an access or refresh token away before it expires.

Invalidate a token you no longer need — when a user signs out of your app, when
you rotate credentials, or when you suspect a token leaked. Follows RFC 7009.

**POST** `/api/auth/oauth2/revoke`

> [!NOTE]
> This revokes **your app's** token. It does not disconnect the app from the
> user's account — the user's approval stays, so the next authorization request
> skips the consent screen. Users disconnect apps themselves under Account →
> Settings → Connections, which also deletes every token your app holds for
> them.

## Authorizations

| Name | Type | In | Required | Description |
| --- | --- | --- | --- | --- |
| `Authorization` | string | header | no | `Basic base64(client_id:client_secret)`. Alternatively send both as form fields. |
| `client_id` | string | body | no | Your app's client ID, if you are not using the Basic header. |
| `client_secret` | string | body | no | Your app's secret. Client authentication is required. |

## Body

The body must be `application/x-www-form-urlencoded`.

| Name | Type | In | Required | Description |
| --- | --- | --- | --- | --- |
| `token` | string | body | yes | The access token or refresh token to revoke. |
| `token_type_hint` | string | body | no | `access_token` or `refresh_token`. Only a hint — the endpoint looks the token up either way. |

## Example Request

  #### cURL

```bash
curl -X POST "https://haunt.gg/api/auth/oauth2/revoke" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
  -d "token=YOUR_REFRESH_TOKEN" \
  -d "token_type_hint=refresh_token"
```
  #### JavaScript

```ts
await fetch("https://haunt.gg/api/auth/oauth2/revoke", {
  method: "POST",
  headers: {
    "Content-Type": "application/x-www-form-urlencoded",
    Authorization: `Basic ${btoa(`${CLIENT_ID}:${CLIENT_SECRET}`)}`,
  },
  body: new URLSearchParams({ token, token_type_hint: "refresh_token" }),
});
```

## Response

  #### 200 — Done. As RFC 7009 requires, an unknown, already-revoked or foreign token is not an error — the response is a success either way, so revocation is safely idempotent.

```json
null
```
  #### 400 — No token was sent.

```json
{
  "error": "invalid_request",
  "error_description": "missing a required token for introspection"
}
```
  #### 401 — Client authentication is missing or wrong.

```json
{
  "error": "invalid_client",
  "error_description": "missing required credentials"
}
```

## Rate limit

100 requests per minute per IP address, counted for this endpoint alone.
