> ## Documentation Index
> Fetch the complete documentation index at: https://veriqa.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Confirming a sensitive operation in a messenger

> Recipe: a transfer, an email change or a data deletion runs only after it is confirmed in a messenger. How to choose between step-up and the server-to-server confirmation API, and what to do for each.

The user is already signed in, but before a transfer, an email change or a data deletion you want
them to confirm the action again — with a tap in a messenger, not an SMS code.

## Which one to choose

Both Veriqa mechanisms fit. They differ in what the user sees and where the confirmation starts.

| | Step-up | Server-to-server confirmation API |
| - | - | - |
| Who starts it | The user's browser: a new authorize request | Your backend: an API call |
| What the user reads in the messenger | A sign-in confirmation with the [initiator context](/docs/concepts/initiator-context): the app, browser, OS and region | The text of the action itself, from your template, such as "Approve a payment of €500?" |
| How you know the account owner confirmed | Compare the `sub` in the new `id_token` with the signed-in user | `expected_identities` in the request and `matched_type` in the result |
| What you get | An `id_token` with a fresh `auth_time` | An outcome: `confirmed`, `declined`, `expired` or `failed` |

**How to choose.** If the message has to name the operation itself — the amount, the payee, the new
address — or the action does not start in the user's browser, use the server-to-server confirmation
API. If you only need to make sure the user is at the screen right now, step-up is enough.

## What you need

* a Veriqa server with a channel enabled and an app connected to it — for example, by the
  [Passwordless sign-in for a web app](/docs/recipes/web-app-sign-in) recipe;
* access to the backend that performs the operation.

## Steps: step-up

<Steps>
  <Step title="Send a new authorize request before the action">
    A regular sign-in request with no special parameters — [What you send](/docs/scenarios/step-up#what-you-send).
  </Step>

  <Step title="Check auth_time">
    Perform the operation only if the `auth_time` in the new `id_token` is within your freshness
    window — [What you check](/docs/scenarios/step-up#what-you-check).
  </Step>

  <Step title="Narrow the channel if needed">
    The `acr_values` parameter sends the confirmation to a specific channel —
    [Going stronger: two different channels](/docs/scenarios/step-up#going-stronger-two-different-channels).
  </Step>
</Steps>

## Steps: server-to-server confirmation API

<Steps>
  <Step title="Declare the action type">
    In the client record, describe the action type: its slots and the message text —
    [Configure the client](/docs/reference/confirmation-api#1-configure-the-client).
  </Step>

  <Step title="Create the confirmation">
    The backend gets a token with client credentials and calls `POST /api/transaction/confirmation`,
    passing the account owner's identity in `expected_identities` —
    [steps 2–3](/docs/reference/confirmation-api#2-get-a-token).
  </Step>

  <Step title="Show the QR code or the link">
    Display the `channel_entry` from the response on the user's screen —
    [Create the confirmation](/docs/reference/confirmation-api#3-create-the-confirmation).
  </Step>

  <Step title="Wait for the outcome">
    Poll `GET /api/transaction/{id}/result` and perform the operation on `confirmed` with a matching
    `matched_type` — [Read the outcome](/docs/reference/confirmation-api#4-read-the-outcome).
  </Step>
</Steps>

## How to check

Start the operation and confirm it on your phone — the operation should run. Then repeat and decline
the confirmation: the operation should not run. For the server-to-server confirmation API, also
confirm from another account: `matched_type` in the result should stay `null`.

## Next steps

* [Step-up, second factor, human-in-the-loop](/docs/samples/confirmation) — three working samples built on
  the server-to-server confirmation API, including a project deletion that only the owner can confirm;
* [Approving AI-agent actions](/docs/scenarios/agent-approvals) — the same API for an agent's steps;
* [Basic scenarios](/docs/basic-scenarios) — when you need a sign-in and when a server-to-server
  transaction.


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