Revoke Endpoint
RFC 7009 token revocation — the server half of a client's logout.
Q-1575: until this existed the AS advertised no revocation_endpoint, so a compliant client could only forget its copy of the token. Measured on prod 2026-09-19: codex mcp logout keel cleared the local keychain entry while the org's platform.agent_credentials row kept revoked_at = NULL — a live refresh credential, carrying whatever scopes it was minted with, on an org whose owner believed they had disconnected that agent.
Posture, deliberately identical to /token:
- Public client, no client authentication. That is what token_endpoint_auth_methods_supported: ["none"] already advertises and what every MCP client here is. The bearer of the token is the only party who can present it, and presenting it IS the authorization to destroy it — revocation only ever removes capability, so an attacker who already holds the token gains nothing by calling this.
- Form-encoded or JSON body (:func:_parse_token_body), and the same invalid_request 401 as the token endpoint for a malformed call, so this router has one error posture rather than two.
RFC 7009 §2.2: an unknown, expired, or already-revoked token answers 200 with an empty body. The endpoint never discloses whether a token was ever valid, so it cannot be used as a validity oracle.
A refresh token revokes its whole rotation chain (lineage_id), not merely the row presented. Rotation means the token a client holds is a descendant of the one it first received; killing one link while its siblings live would leave the grant alive and the user's "disconnect" still a lie. This is the same lineage burn reuse detection performs in :func:_do_refresh.
Access tokens are stateless 1h JWTs with no row to revoke, so a token_type_hint=access_token call still answers 200 (RFC 7009 §2.1: the server extends its search across its supported token types; finding nothing is not an error). Revoking the refresh chain stops renewal, and the last access token minted from it expires on its own within the hour.
Request
- Base URL: https://api.usekeel.io (the document declares no server; this is the origin it was published from)
- URL: https://api.usekeel.io/v1/auth/oauth/revoke
- Auth: none declared
Response
Successful Response
Changes
No recorded changes to this operation across all 1 revision of this API.