> ## Documentation Index
> Fetch the complete documentation index at: https://ramps-feat-striga-sca-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Two-factor reset

> Recover a customer who has lost their SCA factor

<Note>
  Applies only to customers in an SCA-required region (EU). Every endpoint here
  returns **`409`** for other customers.
</Note>

When a customer loses an enrolled factor (a new phone, a deleted authenticator),
they recover it with a **2FA reset**: an identity (liveness) check that, once
passed, clears the lost factor so they can re-enroll it. It's a poll-based flow:
start, poll until liveness passes, then complete.

All paths below are relative to `https://api.lightspark.com/grid/2025-10-13`.

<Steps>
  <Step title="Start the reset">
    ```bash theme={null}
    POST /sca/factors/reset?customerId={customerId}

    { "factor": "TOTP" }
    ```

    Returns **`201`** with a `resetId` and opaque liveness handles. Embed
    `livenessAccessToken` in the verification SDK, or send the customer to
    `verificationLink`. `expiresAt` bounds the reset window. Reset initiation is
    rate-limited to **5 per 24 hours** per customer; beyond that this returns `429`.

    ```json theme={null}
    {
      "resetId": "…",
      "livenessAccessToken": "…",
      "verificationLink": "https://…",
      "expiresAt": "2025-10-03T12:30:00Z"
    }
    ```
  </Step>

  <Step title="Poll until liveness passes">
    ```bash theme={null}
    GET /sca/factors/reset/{resetId}?customerId={customerId}
    ```

    ```json theme={null}
    { "status": "INITIATED" }
    ```

    Poll with a short backoff. `status` is one of `INITIATED`, `PENDING_REVIEW`,
    `LIVENESS_PASSED`, `COMPLETED`, `REJECTED`, or `EXPIRED`:

    * `INITIATED` — reset started, liveness not yet submitted; keep polling.
    * `PENDING_REVIEW` — liveness submitted and under review; keep polling.
    * `LIVENESS_PASSED` — proceed to complete.
    * `COMPLETED` (reset finished, factor cleared), `REJECTED` (liveness failed), and
      `EXPIRED` (window closed) are **terminal** — stop polling. On `REJECTED` or
      `EXPIRED`, start a new reset.

    The response also carries `factor`, `enrollmentStatus` (`PENDING` until the
    replacement factor is re-enrolled, then `COMPLETED`; `null` for an `SMS_OTP`
    reset), `expiresAt` (the window bound), and `completedAt`. Stop at any terminal
    status or once `expiresAt` passes; never poll indefinitely.
  </Step>

  <Step title="Complete the reset">
    ```bash theme={null}
    POST /sca/factors/reset/{resetId}/complete?customerId={customerId}

    { "mobile": { "countryCode": "+1", "number": "4155550123" } }
    ```

    Returns `204` and clears the lost factor. For an `SMS_OTP` reset, include the new
    `mobile` number in the body — it's enrolled as the customer completes the reset;
    other factors need no body. Calling it before liveness has passed returns `400`.
    The customer can then re-enroll via
    [factor enrollment](/platform-overview/sca/factor-enrollment).
  </Step>
</Steps>
