Skip to main content
PATCH
Restrict an existing API key to a single IP address, or clear the restriction so any IP can use it.

Authorization

This endpoint is dashboard-only: a dashboard JWT with role merchant_admin, merchant_member (with team permission api-keys:manage) or super_admin. API-key callers are rejected with 401 {"error":"Invalid or expired token"} — the JWT guard runs first and an API key is not a session token, so the call never reaches the role check. The key is not revoked; it simply cannot authenticate a dashboard-only route. Rate limit: 5/min. MFA is required — same factor rules as Create an API key.

Parameters

string
required
ID of the key to update (from List API keys).
string | null
A single IP to bind to (e.g. 203.0.113.10), or null (or "") to clear the binding. Omitting it also clears the binding.
One strong factor is required on this call: either totpCode or passkeyResponse + challengeKey — same factor rules as Create an API key.
string
6–8 characters: TOTP or backup code. Required unless you pass a passkey assertion instead.
object
WebAuthn assertion (alternative to TOTP). Sent together with challengeKey.
string
Accompanies passkeyResponse.

Response fields

boolean
true on success.
string[]
The key’s resulting IP whitelist.

Errors

Two shapes, and the handler order. Checks run: merchant context → keyId format → ip format → MFA enrolled → MFA verified → key lookup. So an invalid ip returns INVALID_IP before any MFA step, and the 404 is reached only after MFA succeeds — a valid one-time factor (including a backup code) is consumed even when keyId is wrong. The MFA-failure rows (401/403/429 above) send a bare {"error":"..."} string, not the {"ok":false,"error":{"code":…}} envelope the other rows use, and the codes INVALID_OTP/VERIFICATION_FAILED do not exist — branch on the HTTP status for those, not on error.code.

See also