Skip to main content
How a signed-in user recovers when they lose their authenticator app or forget their transaction PIN, without contacting support: Each reset needs two separate factors, so one stolen factor is never enough. This guide is for developers building the dashboard security settings.

Contents


Before you start

  • Base URLs: sandbox https://smtp.yativo.com, production https://api.yativo.com. All paths below include /api/v1.
  • Dashboard only. Every endpoint here needs the signed-in person’s bearer token. They can’t be called with an API key (403 This endpoint cannot be used with an API key. ...).
  • Each person recovers their own account. For a team member these endpoints act on the member’s own 2FA, PIN and passkeys, never the team owner’s. See Team Functionality.
  • A passkey is required for both resets. A user with no passkey can’t reset 2FA or the PIN themselves and gets 403. Encourage users to add a passkey (Passkey Login) when they turn on 2FA.
  • Both resets work while business KYC is still pending.
  • Responses use the standard envelope: { "status": "success" | "failed", "status_code": ..., "message": "...", "data": { ... } }. See API Responses & Errors.

Two-factor authentication

Turn on 2FA and save the recovery codes

  1. Get a secret and show it to the user as a QR code or text:
  2. The user adds it to their authenticator app and enters the current 6-digit code:
Show the 10 recovery codes once and ask the user to save them (download, print or copy to a password manager). They are never shown again. Yativo stores only a one-way hash of each code. Recovery codes:
  • are 10 characters, shown as XXXXX-XXXXX;
  • work once each;
  • ignore case, spaces and the dash; O, I and L are read as 0, 1, 1;
  • are deleted when 2FA is turned off or reset.

Generate new recovery codes

Replaces the whole set; the old codes stop working. Needs a current authenticator code, so it only works while the user still has their app. Users who turned on 2FA before recovery codes existed should do this once.

Reset 2FA with a recovery code

For a user who lost their authenticator app. They sign in with the email one-time code, then:
  1. Get a passkey challenge and sign it (see Passkey confirmation).
  2. Send one recovery code and the signed challenge:
On success:
  • 2FA is turned off and all remaining recovery codes are deleted;
  • the user is emailed a security notice with the time and IP address;
  • the user should turn 2FA on again straight away, which gives them a new set of recovery codes.
The passkey is checked first, so a recovery code is only used up once the passkey has passed.

Transaction PIN

The transaction PIN is a 4-digit code that confirms money movements in the dashboard.

Set or change the PIN

old_pin is required only when a PIN is already set. A wrong old_pin counts towards the PIN lockout.

Verify the PIN

After 5 wrong PINs in 15 minutes (from pin/verify or a wrong old_pin on pin/update), both endpoints return 429 Too many incorrect PIN attempts. Try again in N minutes, or reset your PIN. until the 15 minutes pass or the PIN is reset. A correct PIN clears the count.

Reset a forgotten transaction PIN

Needs 2FA turned on and a passkey on the account.
  1. Get a passkey challenge and sign it (see Passkey confirmation).
  2. Send the current authenticator code, the new PIN and the signed challenge:
On success the PIN lockout is cleared and the user is emailed a security notice with the time and IP address.

Passkey confirmation

Both resets need a fresh passkey signature from the signed-in person.
  1. Get a challenge:
    The response contains data.public_key (rpId, challenge, timeout, allowCredentials). It returns 422 No passkeys registered for this account. when the person has no passkey.
  2. Sign it in the browser on a *.yativo.com page:
  3. Send it as passkey:
A challenge works once and expires after 60 seconds. If a reset request fails, get a new challenge before retrying. More detail: Passkey Login → Confirming a sensitive action.

Limits

A per-minute limit returns 429 Too Many Attempts. with a Retry-After header.

Errors


Frontend flow

Security settings page
  • 2FA off → “Turn on 2FA” → generate-2fa-secret → enable-2fa → show the recovery codes with “Download” / “Copy” and an “I’ve saved them” checkbox.
  • 2FA on → “Generate new recovery codes” (asks for an authenticator code).
  • No passkey → prompt “Add a passkey so you can recover your account”.
“Lost your authenticator?” (on the 2FA prompt)
  1. Ask for a recovery code.
  2. Call passkeys/step-up/options, sign with navigator.credentials.get().
  3. POST /2fa/recover → on success, send the user to turn 2FA on again.
“Forgot your PIN?” (on the PIN prompt)
  1. Ask for the new PIN twice and the current authenticator code.
  2. Call passkeys/step-up/options, sign.
  3. POST /pin/reset.

Security notes

  • Recovery codes, PINs and authenticator secrets are never returned by any other endpoint. Codes and PINs are stored as one-way hashes; the authenticator secret is encrypted at rest.
  • A recovery code is accepted only once, and so is the authenticator code sent to pin/reset.
  • Every reset is logged and emailed to the account owner. If a user gets an email for a reset they didn’t make, they should contact support at once.
  • A user who has lost both their authenticator and their recovery codes, or has no passkey, can’t reset 2FA or the PIN themselves and must contact support.