After a 202 from POST /v1/auth/login: send the challenge token with a code from the authenticator app, a recovery code, or a passkey's response (start it with POST /v1/auth/login/mfa/passkey). Each sign-in allows 5 attempts within 5 minutes; each code works once.
Body
application/json
challenge_tokenstringrequired
From the 202 response of POST /v1/auth/login
maxLength: 256
codestring
A code from the authenticator app
maxLength: 16
passkeyobject
A passkey's response, instead of code
2 fields
ceremony_tokenstringrequired
From POST /v1/auth/login/mfa/passkey when signing in, or POST /v1/auth/passkeys/verification when signed in
maxLength: 256
credentialobjectrequired
The PublicKeyCredential from navigator.credentials.get(), as JSON
recovery_codestring
A recovery code, instead of code
maxLength: 32
transportstring
cookie (browsers): an HttpOnly session cookie; bearer (native apps): the token in the response
one of: cookie, bearerdefault: "cookie"
Responses
errors: application/problem+json
200
OK
401
Unauthorized
422
Unprocessable Entity
429
Too Many Requests
500
Internal Server Error
503
Service Unavailable
Match errors on the problem's code, which stays the same, not on its message.