---
title: "Verify a challenge on a factor."
method: POST
path: "/factors/{factorId}/verify"
tags: ["user"]
---

# Verify a challenge on a factor.

`POST /factors/{factorId}/verify`

## Path parameters

- `factorId` string, uuid, required

## Request body

- object
  - `challenge_id` string, uuid, required
  - `code` string
  - `webauthn` object
    - `type` 'create' | 'request', required — Type of WebAuthn operation
    - `credential_response` object, required — WebAuthn credential response from the client

## Response `200`

This challenge has been verified. Client libraries should replace their stored access and refresh tokens with the ones provided in this response. These new credentials have an increased Authenticator Assurance Level (AAL).

- AccessTokenResponseSchema
  - `access_token` string — A valid JWT that will expire in `expires_in` seconds.
  - `refresh_token` string — An opaque string that can be used once to obtain a new access and refresh token.
  - `token_type` string — What type of token this is. Only `bearer` returned, may change in the future.
  - `expires_in` integer — Number of seconds after which the `access_token` should be renewed by using the refresh token with the `refresh_token` grant type.
  - `expires_at` integer — UNIX timestamp after which the `access_token` should be renewed by using the refresh token with the `refresh_token` grant type.
  - `weak_password` object — Only returned on the `/token?grant_type=password` endpoint. When present, it indicates that the password used is weak. Inspect the `reasons` and/or `message` properties to identify why.
    - `reasons` string[]
    - `message` string
  - `user` UserSchema — Object describing the user related to the issued access and refresh tokens.
    - `id` string, uuid
    - `aud` string
    - `role` string
    - `email` string — User's primary contact email. In most cases you can uniquely identify a user by their email address, but not in all cases.
    - `email_confirmed_at` string, date-time
    - `phone` string, phone — User's primary contact phone number. In most cases you can uniquely identify a user by their phone number, but not in all cases.
    - `phone_confirmed_at` string, date-time
    - `confirmation_sent_at` string, date-time
    - `confirmed_at` string, date-time
    - `recovery_sent_at` string, date-time
    - `new_email` string, email
    - `email_change_sent_at` string, date-time
    - `new_phone` string, phone
    - `phone_change_sent_at` string, date-time
    - `reauthentication_sent_at` string, date-time
    - `last_sign_in_at` string, date-time
    - `app_metadata` object
    - `user_metadata` object
    - `factors` MFAFactorSchema[]
      - `id` string, uuid
      - `status` string — Usually one of: - verified - unverified
      - `friendly_name` string
      - `factor_type` string — Usually one of: - totp - phone - webauthn
      - `webauthn_credential` string
      - `phone` string, phone, nullable
      - `created_at` string, date-time
      - `updated_at` string, date-time
      - `last_challenged_at` string, date-time, nullable
    - `identities` IdentitySchema[]
      - `identity_id` string, uuid
      - `id` string, uuid
      - `user_id` string, uuid
      - `identity_data` object
      - `provider` string
      - `last_sign_in_at` string, date-time
      - `created_at` string, date-time
      - `updated_at` string, date-time
      - `email` string, email
    - `banned_until` string, date-time
    - `created_at` string, date-time
    - `updated_at` string, date-time
    - `deleted_at` string, date-time
    - `is_anonymous` boolean

## Other responses

- `400` — HTTP Bad Request response. Can occur if the passed in JSON cannot be unmarshalled properly or when CAPTCHA verification was not successful. In certain cases can also occur when features are disabled on the server (e.g. sign ups). It may also mean that the operation failed due to some constraint not being met (such a user already exists for example).
- `429` — HTTP Too Many Requests response, when a rate limiter has been breached.

## Changes

- **2026-04-28** `d3f7d49a0bd6` — 2 warning
  - removed the request property `webauthn/rpId`
  - removed the request property `webauthn/rpOrigins`
- **2025-09-24** `a222d9459767` — 1 warning, 2 info
  - removed the optional property `user/factors/items/web_authn_credential` from the response with the `200` status
  - added the new optional request property `webauthn`
  - added the optional property `user/factors/items/webauthn_credential` to the response with the `200` status
- **2025-02-07** `4d0f1a6c1ad9` — 1 breaking, 1 info
  - the `user/factors/items/web_authn_credential` response's property type/format changed from `jsonb`/`` to `string`/`` for status `200`
  - added the optional property `error_code` to the response with the `400` status
- **2024-10-11** `f89bf040698f` — 1 breaking, 4 info
  - the response property `user/factors/items/phone` became nullable for the status `200`
  - added the optional property `user/factors/items/created_at` to the response with the `200` status
  - added the optional property `user/factors/items/last_challenged_at` to the response with the `200` status
  - added the optional property `user/factors/items/updated_at` to the response with the `200` status
  - …1 more
- **2024-08-01** `b33a9ea8493e` — 1 info
  - added the optional property `user/factors/items/phone` to the response with the `200` status

[Full history](https://skmtc.dev/supabase/apis/supabase-auth-rest-api/changes/factors/:factorId/verify/post.md)

---

[API](https://skmtc.dev/supabase/apis/supabase-auth-rest-api.md) · [All operations](https://skmtc.dev/supabase/apis/supabase-auth-rest-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/supabase/supabase-auth-rest-api/revisions/2e2a74a7459f/schema)
