> ## Documentation Index
> Fetch the complete documentation index at: https://agents-docs.lightspark.com/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.

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`.

**1. Start the reset**

```bash theme={null}
POST /sca/factors/reset?customerId={customerId}

{ "factor": "TOTP", "endUserIpAddress": "203.0.113.42" }
```

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"
}
```

**2. 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.

**3. Complete the reset**

```bash theme={null}
POST /sca/factors/reset/{resetId}/complete?customerId={customerId}

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

Returns `204` and clears the lost factor. The body is required and must carry
`endUserIpAddress`. For an `SMS_OTP` reset, also include the new `mobile` number —
it's enrolled as the customer completes the reset; other factors need no `mobile`.
Calling it before liveness has passed returns `400`.
The customer can then re-enroll via
[factor enrollment](https://agents-docs.lightspark.com/platform-overview/sca/factor-enrollment.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.