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

# Digital ID wallet APIs

> Verify identity through a digital ID wallet from your own application, without creating a verification workflow.

Use a dedicated wallet endpoint to verify a person from your own application.
You do not need to create or publish a workflow, or provide a `workflow_id`.
Your backend starts the verification and retrieves its result; your interface guides the person through the wallet's required authentication.

<Note>
  An API integration still requires the person to authenticate and approve sharing their identity.
  You cannot verify someone by submitting their personal identifier without that interaction.
</Note>

## How verification works

1. Your backend checks the [wallet catalog](/standalone-apis/digital-id-wallet-catalog), then calls an available wallet's start endpoint using your application API key.
2. Didit returns a verification reference and the action the person needs to take.
3. Your application opens the authentication page or displays the wallet's approval instructions.
4. The person authenticates with their wallet.
5. Your backend retrieves the verified result and handles completion notifications.

Wallet authentication is asynchronous.
A successful start request means authentication has started; it does not mean the identity has been verified.
Always check the final result before treating the person as verified.

## Backend integration

Use [List digital ID wallets](/standalone-apis/digital-id-wallet-catalog) to obtain the current endpoints, required fields and availability for your application.

Keep your `x-api-key` on your backend.
Do not place it in a browser bundle or mobile application.
Use a distinct `Idempotency-Key` for each new verification attempt and reuse that key when retrying the same start request.
Changing the request while reusing its key is a conflict, not a new verification attempt.

Each wallet has its own start URL, such as `/v3/id-verification/wallets/ftn/` for Finnish Trust Network.
The `request_id` identifies the standalone verification for subsequent operations.
Use `vendor_data` for your own reference, up to 2,000 UTF-8 bytes, and `metadata` for an optional JSON object.
Both are returned with the result and completion webhook.

| Operation | Endpoint |
| - | - |
| Read status and result | `GET /v3/id-verification/wallets/verifications/{request_id}/` |
| Poll a phone approval | `POST /v3/id-verification/wallets/verifications/{request_id}/poll/` |
| Cancel a pending verification | `POST /v3/id-verification/wallets/verifications/{request_id}/cancel/` |

These operations use the API key of the application that started the verification.
Polling and authentication availability depend on the selected wallet.

A cancel declines a pending verification without charging for it, and returns a completed one unchanged.
For Smart-ID and Mobile-ID, a cancel that arrives while a poll is checking the approval waits a few seconds for that poll.
It then declines the verification, or returns it as `verified` if the person had already approved.
A verification the person is completing at that moment cannot be cancelled: the response is `409` with `error: "verification_in_progress"` and a `Retry-After` header.
Retry after that many seconds to read the completed result.

## Register your return destination

Redirect wallets send the person back to your application after authentication.
Register the exact hostname before starting a verification:

```bash theme={null}
curl --request PATCH \
  --url https://verification.didit.me/v3/webhook/ \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{"allowed_return_hosts": ["app.example.com"]}'
```

Then send an HTTPS `return_url`, such as `https://app.example.com/identity/complete`, in the start request.
Use bare hostnames in `allowed_return_hosts`, without a scheme, path or wildcard.
Register each subdomain you use separately, up to 20 hostnames.
Updating `allowed_return_hosts` replaces the registered list, so include every hostname you want to keep.
`GET /v3/webhook/` returns the current list; see [Webhook configuration](/sessions-api/management-api#webhook-configuration).
You do not need a workflow or a white-label domain to register a return destination.
The destination is a browser return page; configure completion webhooks separately for your backend.

## Example: Finnish Trust Network

After registering your return hostname, start a Finnish Trust Network verification:

```bash theme={null}
curl --request POST \
  --url https://verification.didit.me/v3/id-verification/wallets/ftn/ \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'Idempotency-Key: your-unique-attempt-key' \
  --header 'Content-Type: application/json' \
  --data '{
    "country": "FIN",
    "return_url": "https://app.example.com/identity/complete",
    "vendor_data": "your-customer-reference"
  }'
```

Save the returned `request_id` and send the person's browser to `wallet_verification.next_action.url` when its `type` is `redirect`.
After the person returns, retrieve the result from your backend:

```bash theme={null}
curl --request GET \
  --url https://verification.didit.me/v3/id-verification/wallets/verifications/REQUEST_ID/ \
  --header 'x-api-key: YOUR_API_KEY'
```

Check `wallet_verification.outcome`:

| Outcome | Meaning |
| - | - |
| `pending` | Authentication is still in progress. |
| `verified` | Authentication completed and the returned identity is verified. |
| `cancelled` | The person or your application cancelled the attempt. |
| `timeout` | The authentication window expired. |
| `failed` | Authentication or identity validation failed. |

Only use the identity when the outcome is `verified` and `simulated` is `false` for a real identity check.
A pending response can carry a next action; terminal responses have no next action.

## Authentication experiences

**Redirect wallets** return an authentication URL.
Open that URL in the person's browser, let them complete the wallet's authentication process and return them to your registered destination.
Read the result from your backend instead of trusting a return URL parameter as proof of identity.

**Smart-ID and Mobile-ID** use an approval prompt on the person's phone.
Your interface collects the required personal identifier; Mobile-ID also needs the associated phone number.
Display the comparison code and instruct the person to approve only when it matches the code on their phone.
Their PIN belongs in the wallet or phone prompt, never in your form or an API request.
Poll from your backend at the returned `poll_interval_seconds` for prompt feedback.
Didit also checks pending phone approvals in the background, so completion can reach your webhook after the person closes your page.

The available interaction depends on the selected wallet.
Do not assume every wallet supports an embedded form, a QR code or authentication without a browser.

## Completion webhooks

Configure an application webhook destination for `status.updated` using the [webhook integration guide](/integration/webhooks).
Use `webhook_version: "v3"` for the decision structure described here.
Verify the webhook signature on your backend before processing it.
The webhook's `session_id` matches the `request_id` returned by the wallet API.
A completed wallet identity appears in the webhook's `decision.id_verifications` array with `verification_method: "wallet"`.
You can also use the identifier to retrieve the dedicated wallet API result.

Handle approval and decline notifications, including cancelled and expired verifications.
Make your webhook handler idempotent because failed deliveries are retried.
A browser return is not a completion webhook and its query parameters are not proof of identity.

## Returned identity

Use the normalized identity fields for names and dates of birth when those fields are returned.
Wallet-specific attributes describe the identity information shared by the selected wallet.
The available attributes vary by wallet and country.
An authenticated identity does not imply that a portrait, address or every other requested attribute is available.

## Test in sandbox

An application in Didit sandbox mode simulates wallet verification without contacting a wallet provider or charging credits.
The response identifies these requests with `wallet_verification.simulated: true`.
A simulated approval is sample data, not a verified real-world identity.

For a redirect wallet, follow the returned URL to exercise the callback and return to your application.
For Smart-ID or Mobile-ID, use the polling endpoint to complete the simulated approval; no notification is sent to a phone.
To test failure handling, set `sandbox_scenario` to `wallet_cancelled`, `wallet_timeout` or `wallet_provider_error` when starting a request.
Live applications reject `sandbox_scenario`.

Didit sandbox simulation is separate from testing against a provider's own test environment.
Successful simulation does not establish live provider access or production availability.

## Availability and pricing

Endpoint coverage and production wallet activation are separate.
A wallet can have an API reference page while remaining unavailable for live authentication.
Check the wallet's country coverage and production status before implementing a live journey.

See [digital ID wallet pricing](/getting-started/pricing#digital-id-wallet-pricing) for published rates and availability.
Wallet verification is separate from document capture and the free monthly document-verification allowance.

## Choosing an integration

Use these APIs when you want to own the surrounding interface and application logic.
Use the [Sessions API](/sessions-api/create-session) when you want Didit's hosted verification journey, workflow rules and configured fallback steps.
Both approaches still require the wallet's authentication and consent process.


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