> For the complete documentation index, see [llms.txt](https://docs.ur.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ur.app/getting-started/integration-guide.md).

# Choose your integration options

UR is modular. You build your integration from three independent decisions: how your platform connects (Account Mode), how card spend settles (Card Mode), and how users verify identity (KYC Mode). Each decision stands on its own, so any combination of options works.

## Three decisions

Before integration kicks off, confirm one option from each:

| Decision                          | Options                                                                      | What it determines                                          |
| --------------------------------- | ---------------------------------------------------------------------------- | ----------------------------------------------------------- |
| [**Account Mode**](#account-mode) | Managed Custody Mode · External Wallet Access Mode (+ legacy Delegated Mode) | How your platform connects to UR and who signs transactions |
| [**Card Mode**](#card-mode)       | Fiat Only · Crypto Backed · No card                                          | Where card spend draws funds from                           |
| [**KYC Mode**](#kyc-mode)         | UR-hosted webview · Sumsub SDK in your app · Sumsub reuse (share token)      | How the user completes identity verification                |

Once these three are fixed, the rest of the integration is a standard menu of Core Banking APIs (Pay-in, Payout, On-ramp (coming soon), Off-ramp, FX, Card) wired against the chosen options.

{% hint style="info" %}
Regardless of which options you choose, your platform is responsible for mapping and maintaining the relationship between your users' identifiers and their corresponding URID. This allows your platform to accurately reflect user states based on UR APIs and webhooks.
{% endhint %}

## Before you start

Every integration starts with the same setup, whichever options you pick. Work through the following steps with UR once:

{% stepper %}
{% step %}

### Contact UR

Contact UR at <support@ur.app>. UR opens your dedicated integration channel, runs due diligence, and starts your onboarding.
{% endstep %}

{% step %}

### Confirm your integration options

Confirm your integration options with UR: your Account Mode, your Card Mode, your KYC Mode, and the services you want.
{% endstep %}

{% step %}

### Check eligibility and limits

Two rules are enforced by UR, not configured by you, and both shape your product before you write any code:

* **Eligibility.** UR checks country and nationality rules when a user opens an account. A user outside the supported lists cannot onboard, no matter how your funnel is built, so design for the rejection path. See [Supported regions](/getting-started/supported-regions.md).
* **Monthly limit.** Every `Live` user carries a rolling monthly limit, denominated in CHF. Outbound and conversion operations (card spend, FX, payout, on-ramp) are checked against it and fail once it is exhausted. Read each user's live limit rather than hardcoding a figure, and subscribe to the `monthly_limit_exceeded` webhook so you can surface it. See [Fetch UR Account information](https://docs.ur.app/api-reference#fetch-ur-account-information) and [Webhooks](/developer-resources/webhook.md).

Raising a user's limit is a compliance review with UR, not an API call.
{% endstep %}

{% step %}

### Generate and register your signing key

Get your signing key and `partnerId`. You have two options: create them in the [API sandbox](https://partner.ur.app/api-sandbox), which generates them for you, or generate an EVM key pair yourself and send UR the public address. Either way, UR issues a `partnerId` that scopes your API calls, and your private key stays on your side. See [API signing key](#api-signing-key) on this page for both paths and the full key lifecycle.
{% endstep %}

{% step %}

### Register your webhook URL

Register your webhook URL with UR so you receive events.
{% endstep %}

{% step %}

### Request sandbox access

Request sandbox access from the UR team. Integrate against sandbox before production.
{% endstep %}

{% step %}

### Go live

Confirm your production configuration with UR, then go live.
{% endstep %}
{% endstepper %}

## Account Mode

Account Mode determines how your platform connects to UR and who controls transaction signing.

### Comparison

| Feature            | Managed Custody Mode                                                                        | External Wallet Access Mode                              | Delegated Mode                                   |
| ------------------ | ------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------ |
| Integration style  | Web2 / API-first                                                                            | Web3 / smart contract-first                              | Web2 / API-first                                 |
| User onboarding    | Partner-managed (Sumsub SDK or UR Webview)                                                  | Partner implements all UIs                               | Redirect user to UR Webview                      |
| Account creation   | API-driven account provisioning                                                             | User signs a message with their wallet to mint a URID    | Redirect to UR Webview                           |
| Transactions       | Partner signs for fiat actions; user signs only for crypto (off-ramp)                       | User signs every action via their wallet                 | API-driven via delegated contract allowances     |
| Asset custody      | Fiat: UR-managed account / Crypto: external (non-UR) wallet, partner-side or the user's own | Self-custody in user's single external wallet            | TEE-based embedded wallet (e.g., Turnkey, Privy) |
| Gas fees           | UR pays (operator wallets)                                                                  | User pays (gasless option available)                     | UR pays (operator wallets)                       |
| Card management    | API-driven                                                                                  | User signature to authorize card creation and settings   | Redirect to UR Card Webview                      |
| Development effort | Lower (standard REST API integration)                                                       | Higher (requires Web3 signatures and wallet connections) | Lower (standard REST API integration)            |

{% hint style="warning" %}
Delegated Mode is a legacy integration. New partners should use Managed Custody Mode or External Wallet Access Mode. See [Delegated Mode](/integration-methods/delegated-mode.md) for existing partners.
{% endhint %}

### When to use each mode

We recommend **Managed Custody Mode** if your users don't have crypto wallets today, or if you want a banking app experience without exposing blockchain mechanics. Your backend calls UR APIs for fiat actions. The user's crypto lives in an external (non-UR) wallet, partner-side or the user's own; the UR-managed account holds fiat only. The user never deals with a wallet for banking actions.

We recommend **External Wallet Access Mode** if your users already manage their own wallets (MetaMask, Rabby, etc.) and expect to sign transactions themselves. You get more control over timing and execution, but you need Web3 infrastructure on your side.

| Your platform looks like...                | We recommend                |
| ------------------------------------------ | --------------------------- |
| Consumer FinTech app, exchange, or neobank | Managed Custody Mode        |
| DApp, Web3 wallet, or DeFi aggregator      | External Wallet Access Mode |

### Managed Custody Mode

{% hint style="info" %}
**Recommended path.** Managed Custody Mode requires the least development effort (standard REST APIs, no Web3 wallet handling). Your backend orchestrates the user's fiat account via UR API; the user's crypto sits in an external (non-UR) wallet, partner-side (managed by your backend) or the user's own. The UR-managed account holds fiat only.
{% endhint %}

Your backend orchestrates the user's fiat account (managed by UR). The user's crypto sits in an external (non-UR) wallet, partner-side or the user's own; the UR-managed account holds fiat only. Users never interact with a wallet for fiat actions.

#### Architecture

```mermaid
flowchart LR

subgraph Partner["Partner Platform"]
PB["Partner Backend"]
end

subgraph UR["UR"]
API["UR API"]
FIAT["User Fiat Account
(UR-managed)
Tokenized deposits, IBAN, Card"]
end

CRYPTO["User Crypto
(external non-UR wallet:
partner-side or user's own)"]

subgraph Settlement["Settlement"]
CHAIN["On-chain Settlement"]
end

PB -->|"API calls\n(partner signs)"| API
API --> FIAT
PB -.->|"Direct management\n(when the wallet is partner-side)"| CRYPTO
FIAT --> CHAIN
CRYPTO --> CHAIN
```

#### How it works

* Your backend calls UR API for all fiat actions (pay-in, payout, FX, on-ramp (coming soon), card).
* UR validates authentication, compliance, and executes on-chain.
* For off-ramp, your backend fetches a quote from UR; crypto is submitted to the UR off-ramp contract from the external (non-UR) wallet that holds it (partner-side or the user's own).
* UR notifies you via webhooks on settlement.

#### User experience

Users complete KYC once during onboarding. After that, all banking actions (fiat and off-ramp) are handled by the partner backend; users are not prompted to sign.

See [Managed Custody Mode](/integration-methods/managed-custody-mode.md) for detailed integration steps and the [API reference](https://docs.ur.app/api-reference/account/managed-custody-mode) for endpoints.

#### Integration SOP

Beyond the common setup in [Before you start](#before-you-start), Managed Custody Mode adds the following checklist:

* Register your mainnet signing key through your integration channel so your backend can make API calls.
* Implement account access authorization in your user onboarding. It has two mandatory parts: an in-app authorization confirmation the user accepts before you enable any banking function, and a confirmation email you send with `legal@ur.app` on BCC. The BCC is mandatory; it is UR's compliance record. See [account access authorization](/integration-methods/managed-custody-mode.md#account-access-authorization).
* Read the [Managed Custody Mode API reference](https://docs.ur.app/api-reference/account/managed-custody-mode) for account creation, profile, pay-in details, payout, FX, off-ramp quote, and card.
* Subscribe to the settlement and status webhooks.
* Map each user ID in your system to the URID issued at user onboarding.

### External Wallet Access Mode

External Wallet Access Mode is for platforms where users bring their own wallet (e.g., MetaMask, Rabby) and maintain full self-custody of their keys.

{% hint style="info" %}
UR does not provision an additional wallet for these users. The URID and fiat balances (tokenized deposits) are managed directly within the user's external wallet.
{% endhint %}

#### Architecture

```mermaid
flowchart LR

subgraph PartnerScope["Partner Platform"]
PFE["Partner Frontend / DApp"]
PBE["Partner Backend"]
end

subgraph UserScope["User"]
ActorUser(("User"))
UW["External Wallet"]
end

subgraph URScope["UR Backend"]
API["Partner API"]
VAL["Compliance / Risk<br/>& Quote Service"]
WH["Event Listener /<br/>Webhooks"]
end

subgraph ContractScope["UR Smart Contracts"]
SC["Token / Deposit /<br/>Router Contracts"]
CHAIN["Fiat Balance / Assets"]
end

%% Flow Logic
ActorUser -- Controls --> UW
UW -- Connects to --> PFE

%% 1. Preparation
PFE -- "1. Request Action" --> PBE
PBE -- "2. Get Quote/Params" --> API
API --> VAL
VAL -- "3. Return Tx Data" --> PBE
PBE -- "4. Pass Data" --> PFE

%% 2. Execution (The key difference: User signs & submits)
PFE -- "5. Request Signature" --> UW
UW -- "6. Sign & Submit Tx" --> SC

%% 3. Settlement
SC --> CHAIN

%% 4. Notification
SC -.-> WH
WH -. "7. Notify Status" .-> PBE
```

#### Request flow

* Partner frontend requests an action from the partner backend.
* Partner backend calls UR API to get quote or transaction parameters.
* UR returns transaction data.
* Partner frontend prompts the user to sign with their wallet.
* User signs and submits the transaction to UR smart contracts.
* UR listens for on-chain events and notifies the partner via webhook.

#### User experience

The experience is Web3-native. Users must connect their wallet and sign messages or transactions to approve actions. Your platform acts as a facilitator, relaying these signatures to UR or guiding the user to interact with smart contracts directly.

See [External Wallet Access Mode](/integration-methods/external-wallet-access-mode.md) for detailed integration steps.

#### Integration SOP

In this mode the URID and the user's fiat balances live in the user's own wallet, and the user signs their own transactions. Fiat transactions settle on Mantle Network, so make sure your users' wallets can interact with Mantle.

Beyond the common setup in [Before you start](#before-you-start), the mode-specific steps are the following:

* Register your mainnet signing key through your integration channel so your backend can make API calls.
* Read the [External Wallet Access Mode API reference](https://docs.ur.app/api-reference/account/external-wallet-access-mode).

## Card Mode

Card Mode determines where card spend draws funds from when your user taps their co-branded debit card. You choose a Card Mode separately from your Account Mode.

### Fiat Only

> The card draws exclusively from the user's UR fiat balance.

Card spend is booked against the user's existing UR fiat balance. The user funds that balance through any of the standard channels: bank pay-in, crypto off-ramp into UR, or transfers from another UR user. No partner-side prefund pool is required.

If the user wants to spend crypto, they first **off-ramp** crypto into their UR fiat balance, then tap the card. The off-ramp and the card swipe are two separate operations.

**Step 1 (optional): Off-ramp, user-initiated, only if the user is starting from crypto**

The user converts crypto to fiat. UR executes the conversion at a quoted rate and credits the user's UR fiat balance.

**Step 2: Card swipe**

The user taps their card. UR authorizes against the available UR fiat balance.

**User experience:** if the user already holds fiat in UR, the swipe is one tap. If they're starting from crypto, they need to off-ramp first.

```mermaid
sequenceDiagram
    participant User as End User
    participant Partner as Partner Platform
    participant UR as UR
    participant MC as Mastercard Network
    participant Merchant

    Note over User, UR: Step 1 (optional): Convert crypto to fiat
    User->>Partner: Initiate off-ramp (e.g. 500 USDC)
    Partner->>UR: Request conversion quote (USDC → EUR)
    UR-->>Partner: Quote returned (e.g. €431 · valid 30s)
    User->>Partner: Confirm
    Partner->>UR: Execute conversion
    UR-->>User: €431 credited to UR fiat balance

    Note over User, Merchant: Step 2: Card spending (draws from UR fiat balance)
    User->>Merchant: Tap UR co-branded card
    Merchant->>MC: Authorization request
    MC->>UR: Route: Authorize €50?
    UR->>UR: Verify user fiat balance
    UR-->>MC: Approved
    MC-->>Merchant: Transaction complete
```

**API reference:** No additional partner-side integration surface. UR handles authorization on-chain against the user's tokenized fiat balance. Use the standard Card endpoints in your Account Mode reference ([External Wallet Access Mode](https://docs.ur.app/api-reference/account/external-wallet-access-mode#id-3-card) or [Managed Custody Mode](https://docs.ur.app/api-reference/account/managed-custody-mode#id-11-card)).

#### Integration SOP

Fiat Only is the lightest card option to set up. The setup is the following checklist:

* Complete the [co-branded card artwork](#co-branded-card-artwork) submission if you brand the card.
* Use the standard Card endpoints in your Account Mode API reference: create card, get card info, set default currency, and card history. There is no card-specific settlement surface to build. See the card sections for [Managed Custody Mode](https://docs.ur.app/api-reference/account/managed-custody-mode#id-11-card) and [External Wallet Access Mode](https://docs.ur.app/api-reference/account/external-wallet-access-mode#id-3-card).

### Crypto Backed

> The card can settle directly against the user's crypto holdings, with no per-swipe off-ramp required.

This mode is for products that need users to spend crypto directly via the card, without manually off-ramping into fiat before each purchase. You do not have to custody the user's crypto for this to work. What matters is that you can reliably debit the user's crypto after a swipe is approved, through centralized custody, a smart contract wallet under your programmatic control, or an equivalent arrangement.

The mechanism is a **Buffer Pool** (also called the *Prefund channel*): you keep your Prefund Account topped up by off-ramping USDC into it, and card authorizations settle in real time from that prefunded balance. You then debit the user's crypto asynchronously after the swipe, using UR's swipe-result webhook as the trigger. UR only reports the fiat swipe amount; you decide, based on your own pricing and conversion logic, how much crypto to debit from the user.

**Phase 1: Prefund (partner-initiated, scheduled)**

You call the UR off-ramp contract on a supported off-ramp chain, converting USDC into your Prefund Account; the Prefund Account is the target account of the off-ramp. Schedule recurring off-ramp calls in your backend to keep the account above the minimum balance agreed with UR, so card authorization capacity stays continuous.

**Phase 2: Card spend (user-initiated, real-time)**

When the user taps their card, UR routes the authorization and asks you via webhook whether to approve, and which source to use. You must respond within **500 ms** so UR can return an `APPROVE` / `DECLINE` to Mastercard within its **1-second** total authorization window; your 500 ms sits inside that 1 second.

Your response picks the funding source:

* Settle against your Prefund Account, and debit the user's crypto yourself after the swipe.
* Settle against the user's UR fiat balance, the same path as a Fiat Only card.

The exact field contract for the authorization callback lives in the [Card Mode: Crypto Backed API reference](https://docs.ur.app/api-reference/cards/crypto-backed-card).

After UR returns the result to Mastercard, UR sends you a follow-up webhook. On a successful `CRYPTO` swipe, **you are responsible** for debiting the equivalent crypto from the user. UR does not move crypto on your behalf. How you enforce the debit is part of your own business logic, and typically relies on a smart contract wallet under your programmatic control or a centralized custody arrangement so the user cannot move the crypto between approval and debit.

**User experience:** Seamless. The user taps and pays. No manual conversion step is required.

**Refund handling:** Any card refund is credited to the user's UR fiat balance, regardless of whether the original spend was settled from digital assets or fiat.

```mermaid
sequenceDiagram
    participant Partner as Partner Platform
    participant ORC as UR Off-ramp Contract
    participant UR as UR
    participant Pool as Prefund Account<br/>(UR Managed Fiat Account)
    participant MC as Mastercard Network
    participant Merchant

    Note over Partner, Pool: Phase 1: Prefund (scheduled, recurring)
    Partner->>ORC: Call off-ramp contract with USDC
    ORC-->>Pool: Credit Prefund Account
    Note over Pool: Minimum balance maintained<br/>for card spending capacity

    Note over Partner, Merchant: Phase 2: Card spending (user-initiated)
    Merchant->>MC: Authorization request (user taps card)
    MC->>UR: Route: Authorize €X?
    UR->>Partner: Webhook: "Approve? CRYPTO or FIAT?"<br/>(respond within 500 ms)
    Partner-->>UR: APPROVE (settle from Prefund Account)
    UR->>Pool: Book spend against Prefund Account
    UR-->>MC: Approved (within 1 s window)
    MC-->>Merchant: Transaction complete
    UR->>Partner: Webhook: authorization.result
    Partner->>Partner: Debit equivalent crypto from user's wallet
```

**Prerequisites for Crypto Backed**

* Ability to make an initial USDC prefund to seed card spending capacity.
* Ability to schedule recurring off-ramp calls that top up your Prefund Account on a supported off-ramp chain.
* Ability to respond to the authorization webhook within 500 ms.
* Ability to reliably debit crypto from the user **after** the swipe is approved (typically via a smart contract wallet under your programmatic control or centralized custody, so the user cannot move funds between approval and debit).
* Operational tolerance for working-float management. If your pool drains below the minimum balance, authorizations begin to decline.

**API reference:** [Card Mode: Crypto Backed](https://docs.ur.app/api-reference/cards/crypto-backed-card) plugs into either Account Mode. Three integration surfaces: [Prefund account](https://docs.ur.app/api-reference/cards/crypto-backed-card#id-3-prefund-account), [Card authorization callback](https://docs.ur.app/api-reference/cards/crypto-backed-card#id-4-card-authorization-callback-ur-greater-than-partner), [Card Mode webhooks](https://docs.ur.app/api-reference/cards/crypto-backed-card#id-5-card-mode-webhooks).

#### Integration SOP

Crypto Backed takes the most setup of the three card options, and the order matters. Work through the following steps:

{% stepper %}
{% step %}

### Request Crypto Backed

Tell UR through your dedicated integration channel that you want Card Mode: Crypto Backed. There is no API to enable it.
{% endstep %}

{% step %}

### Complete KYB

Complete KYB (Know Your Business) with UR. UR requires KYB before it provisions your Prefund Account.
{% endstep %}

{% step %}

### UR provisions your Prefund Account

UR provisions your [Prefund Account](https://docs.ur.app/api-reference/cards/crypto-backed-card#id-3-prefund-account). It is one account per partner, and it can hold a balance in more than one settlement currency.
{% endstep %}

{% step %}

### Agree your settlement currencies

Tell UR which settlement currencies your Prefund Account should hold. It defaults to USD. Your settlement currency affects your off-ramp pricing, so agree it before onboarding rather than after you go live.
{% endstep %}

{% step %}

### Choose your settlement mode

Your settlement mode decides who picks the debit currency on each swipe, and whether UR can pre-compute the amount for you:

* **Fixed** (the default) means UR pre-computes the exact amount it will debit, including FX and interchange, and sends it in the authorization request. You approve or decline against that amount and run no conversion. You do not pick the debit currency per swipe.
* **Partner controlled** means you pick which of your settlement currencies to debit on each swipe. UR cannot pre-compute the amount, because it does not know your choice in advance, so you size the debit yourself.

Start with Fixed unless you need per-swipe currency control. See the [settlement modes reference](https://docs.ur.app/api-reference/cards/crypto-backed-card#id-4.1-settlement-modes).
{% endstep %}

{% step %}

### Agree the funding parameters and minimum balances

Agree the off-ramp chain and the deposit currency (USDC only today) with UR.

Agree a **minimum balance for each settlement currency**. Thresholds are per currency, not per account, and UR emits a `prefund.balance.alert` when a currency reaches or falls below its threshold. Set each one above the float you need to absorb a normal day of swipes; when a currency runs dry, authorizations in that currency start to decline.
{% endstep %}

{% step %}

### Receive your Prefund Account details

UR gives you your Prefund Account details. You use the Prefund Account as the target account when you off-ramp.
{% endstep %}

{% step %}

### Register your card authorization callback URL

Register your [card authorization callback](https://docs.ur.app/api-reference/cards/crypto-backed-card#id-4-card-authorization-callback-ur-greater-than-partner) URL with UR. UR calls it on every card authorization. Changing the URL later is coordinated with UR and paired with signature validation; there is no self-serve endpoint.
{% endstep %}

{% step %}

### Seed and maintain the Prefund Account

At mainnet launch, call the off-ramp contract to convert USDC into your Prefund Account and seed card spending capacity. Schedule recurring off-ramps in your backend to keep the Prefund Account topped up.
{% endstep %}
{% endstepper %}

### No card

Choose No card if your platform does not issue cards. Every other service in your integration (pay-in, payout, FX, off-ramp) works the same without one.

#### Integration SOP

There is nothing to set up and nothing to build. The Card endpoints, the card authorization callback, and the card artwork submission do not apply.

## KYC Mode

UR is a regulated financial product. Every user must complete KYC (Know Your Customer) checks before accessing core banking features. You choose *how* KYC is delivered to your users. The right option depends on whether you already verify users with Sumsub today.

For the full list of what UR verifies and the data UR collects, see [KYC & Compliance](/concepts/kyc-and-compliance.md). That page covers identity methods, including NFC, penny transfer, and video verification, plus domicile checks, questionnaire categories, and AML/sanctions screening. This section focuses on integration, not data collection.

### Choosing a method

Identity verification uses an NFC scan, so the user needs an NFC-capable mobile device; on the UR-hosted webview, UR runs that scan for you.

```mermaid
flowchart TD
  Start([Choosing how KYC runs])
  Q1{Already verify users in<br/>your own Sumsub tenant?}
  M3[Sumsub reuse<br/>share token]
  Q2{Run KYC inside<br/>your own app?}
  M1[UR-hosted webview]
  M2[Sumsub SDK in your app]

  Start --> Q1
  Q1 -- Yes --> M3
  Q1 -- No --> Q2
  Q2 -- No --> M1
  Q2 -- Yes --> M2

  style M3 fill:#f0fff4,stroke:#38a169
```

**Which method fits you**

* **UR-hosted webview** if you have no KYC vendor and no mobile app of your own. UR runs the identity scan for you inside its webview.
* **Sumsub SDK in your app** if you want KYC inside your own app and you have a mobile app to run the identity scan.
* **Sumsub reuse (share token)** if you already verify your users in your own Sumsub tenant.

**Upsides and downsides**

| Method                                                                    | Upsides                                                                                                                                                 | Downsides                                                                                                                          |
| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| **UR-hosted webview**                                                     | Lowest effort; no KYC vendor of your own. UR runs the identity scan for you.                                                                            | The user leaves your app for UR's webview, so you have less control over the experience. KYC data lands in UR's Sumsub, not yours. |
| **Sumsub SDK in your app**                                                | KYC feels native in your app. Minimal setup: integrate the Sumsub SDK and run UR's verification workflow through it, with no Sumsub tenant of your own. | KYC data lands in UR's Sumsub, not yours.                                                                                          |
| **Sumsub reuse (share token)** *(recommended if Sumsub already in place)* | No re-verification for users you have already verified. The verification data already lives in your own Sumsub tenant.                                  | You run your own Sumsub tenant and automate the share-token handoff. Works only for users you have already verified.               |

**Where the KYC data lands**

* **UR-hosted webview** and **Sumsub SDK in your app**: the verification is created in UR's Sumsub tenant.
* **Sumsub reuse (share token)**: the data already lives in your own Sumsub tenant; you share it to UR.

### UR-hosted webview

Your platform redirects the user to a UR-hosted webview, where the full KYC flow runs end to end. You need no KYC vendor of your own; UR delivers outcomes via the [`kyc_status` webhook](/developer-resources/webhook.md).

**Happy path**

* You redirect the user to UR's webview after partner-side authentication.
* The user completes the questionnaire, the domicile (device location) check, and Form A signing in the UR webview.
* For identity verification, the user completes the passport/national-ID NFC scan, the document scan, and the selfie in **ReadID**, opened as the ReadID app on Android or as an [App Clip](https://developer.apple.com/app-clips/) on iOS. UR orchestrates this handoff for you.
* UR notifies you via the `kyc_status` webhook when KYC reaches `Live`.

**When to use it:** Choose this path if you have no KYC vendor, or no mobile app of your own. You do not build the NFC scan; UR orchestrates the identity-verification handoff to ReadID for you. The user still completes the scan in ReadID on an NFC-capable mobile device.

#### Integration SOP

This method has no off-code setup beyond the common steps in [Before you start](#before-you-start). Build the redirect and consume the `kyc_status` webhook; there is nothing extra to request, sign, or configure.

### Sumsub SDK in your app

You integrate the Sumsub SDK in your app and run UR's verification workflow through it; you do not run a Sumsub tenant of your own. UR's backend issues the token that starts the SDK. Setup is minimal: the SDK integration plus one backend call.

**Happy path**

* Your backend calls `POST /api/v1/sumsub/create-access-token` for the user. See [Section 2.1.5 in the API reference](https://docs.ur.app/api-reference/account/external-wallet-access-mode).
* Your frontend initializes the Sumsub SDK with the returned `token`.
* User completes KYC inside the partner app, including questionnaire, identity verification, domicile check, and Form A.
* UR notifies the partner via the `kyc_status` webhook on completion.

The NFC scan runs in the Sumsub mobile SDK, so this method needs a mobile app. If your platform is web only, use the **UR-hosted webview** instead, where UR runs the NFC scan for you. Penny transfer is an alternative for users who cannot complete an NFC scan (FATF jurisdictions); see [KYC & compliance](/concepts/kyc-and-compliance.md).

**When to use it:** You want KYC to feel native inside your app, you have a mobile app for the NFC scan, and you have the engineering capacity to integrate Sumsub.

#### Integration SOP

This method has no off-code setup beyond the common steps in [Before you start](#before-you-start). Integrate the Sumsub SDK, call the token endpoint, and consume the `kyc_status` webhook; there is nothing extra to request, sign, or configure.

### Sumsub reuse (share token) *(recommended if already on Sumsub)*

If you have already verified the user with Sumsub on your own tenant, you can share that verification with UR through Sumsub's **share-token** mechanism. UR reruns the required checks against UR's verification level. In the happy path, the user is not prompted again.

**Prerequisites**

* Your platform uses Sumsub.
* You and UR have configured each other as **Donor / Recipient Partners** in the Sumsub dashboard.
* A Data Processing Agreement (DPA) is in place between your company and UR.
* Your KYC flow presents the [required data-sharing declaration](#kyc-data-sharing-disclosure) to the user and captures their agreement before identity verification. Your privacy notice also discloses the share to UR.

{% hint style="warning" %}
**Required KYC disclosure for data sharing.** This option shares the user's verified KYC profile with UR through Sumsub's Reusable KYC network. This is a KYC requirement: your KYC flow must present the following declaration to the user and capture their agreement before they start identity verification. Surface it in your own KYC steps; UR does not show it for you on this path. Use this exact wording:

> By proceeding with identity verification, I acknowledge and agree that my KYC information and verification results may be shared by us and/or Sumsub with Participating Verification Partners within Sumsub's Reusable KYC network for identity verification, anti-money laundering compliance, sanctions screening, regulatory compliance, fraud prevention, and other legal or regulatory purposes, including compliance requirements applicable to such Participating Verification Partners that may be independent from the specific products or services offered on our platform. For the purpose of this declaration, "Participating Verification Partners" means any third-party that participates in Sumsub's Reusable KYC network.

This declaration is the user-facing basis for the Sumsub share-token reuse below. It complements the Data Processing Agreement (DPA), which governs the share between your company and UR.
{% endhint %}

**Happy path**

* Your backend listens for Sumsub's `applicantReviewed` webhook on your tenant.
* On approval, your backend calls Sumsub to generate a **share token** scoped to UR's `clientId`.
* Your backend submits the share token together with your internal user reference to UR through the channel agreed with UR integration support.
* UR calls Sumsub `reuse` against UR's verification level. Selfie/liveness is reused from the donor profile.
* UR notifies you via the `kyc_status` webhook with the result.

**When to use it:** Your users have already been verified on your Sumsub tenant and you want to onboard them to UR without re-verification.

**What this option is not:** UR does not accept raw KYC data exports through your app token. The share-token reuse flow is the only supported backend path because it produces a verification attestation on UR's Sumsub tenant, which is required for UR's Customer Due Diligence (CDD) obligations.

#### Integration SOP

This method shares verification data between two companies, so it carries real off-code prerequisites. Complete the following before the first user flows through:

* Coordinate the setup with UR through your dedicated integration channel.
* Run your own Sumsub tenant.
* Configure UR and your platform as Donor / Recipient Partners in the Sumsub dashboard.
* Sign a Data Processing Agreement (DPA) with UR.
* Present the [required data-sharing declaration](#kyc-data-sharing-disclosure) to the user verbatim and capture their agreement before identity verification starts. UR does not show it for you on this path.

### Where to read more

This page focuses on the *integration* contract. For the underlying KYC process, including what UR verifies, the data UR collects, identity-verification methods, proof-of-address constraints, AML/sanctions screening, and URID status outcomes, see [KYC & compliance](/concepts/kyc-and-compliance.md).

For partner-engineering notes on document uploads: when a user uploads proof-of-address documents through your application, you can pre-filter for the supported languages (English, German, French, Italian) and reject unsupported documents early. Documents in other scripts can still be forwarded to UR. They will be routed to manual review by UR's support team, which adds latency.

## API signing key

UR authenticates every API call with an EIP-191 signature. There are no API keys and no OAuth tokens. Your `partnerId` is bound to a single EVM address, the public address of your signing key. You sign each request with the matching private key; UR recovers the address from the signature and compares it to the address on file for your `partnerId`. If they match, the request is authenticated.

{% hint style="warning" %}
UR never stores your private key. UR stores only your public EVM address. Keep the private key in a secure store such as a hardware security module (HSM) or a key management service (KMS). If you lose it, UR cannot recover it; you must register a new address.
{% endhint %}

You get your signing key and `partnerId` in one of two ways. Both end with the same credential: a `partnerId` plus an EVM key pair whose private key never leaves your side.

### Option 1: create it in the API sandbox *(recommended)*

The [API sandbox](https://partner.ur.app/api-sandbox) generates everything for you, so UR takes no manual action. Your `partnerId` and public address are registered the moment they are created.

{% stepper %}
{% step %}

### Sign in to the sandbox

Sign in at [partner.ur.app/api-sandbox](https://partner.ur.app/api-sandbox). On your first sign-in, the sandbox creates your `partnerId`, public address, and private key, and ties them to your account.
{% endstep %}

{% step %}

### Store your private key

Copy your private key and store it in a secure store (HSM or KMS). UR does not store it and cannot show it again later.
{% endstep %}

{% step %}

### Start signing

Use the private key to sign your API requests. Your `partnerId` and public address are already registered, so no further setup is needed from UR.
{% endstep %}
{% endstepper %}

### Option 2: bring your own EVM address

Generate the key pair yourself with any standard tool and send UR only the public address. Use this path when you want the key to originate in your own infrastructure (for example, a script, a browser wallet such as MetaMask, or a hardware wallet).

{% stepper %}
{% step %}

### Generate the key pair

Generate an ECDSA key pair (an EVM wallet) on your side. Keep the private key in a secure store (HSM or KMS).
{% endstep %}

{% step %}

### Send UR the public address

Send your public EVM address to UR through your integration channel. UR registers the address and issues your `partnerId`. You never send UR the private key.
{% endstep %}

{% step %}

### Start signing

Sign your API requests with the private key. UR verifies each signature against the address you registered.
{% endstep %}
{% endstepper %}

### After setup: sign, verify, and rotate

Once you hold a `partnerId` and key pair from either option, the runtime rules are the same:

* **Sign every request.** Sign each API request with your private key using EIP-191. UR verifies the signature on every call.
* **Verify webhooks.** For webhooks the direction reverses: UR signs the payload, and you verify it against UR's published server address.
* **Rotate when needed.** To rotate keys, register a new address and deregister the old one through your integration channel.

See [Signature and verify](https://docs.ur.app/api-reference/signature-and-verify) for the signing algorithm, the canonical payload format, and code samples.

## Co-branded card artwork

Skip this section if you do not brand the card. The card is virtual, so users add it to Apple Pay or Google Pay. You produce and submit the following through your dedicated integration channel:

* Your card artwork, exported as a flattened PNG at 1536 × 969 pixels, including the debit mark.
* The Copyright Registration for your logo.
* A signed Trademark License Agreement granting UR the right to reproduce your mark.

UR reviews your submission against Mastercard brand standards. Approval takes time, so start early. The full specification, the template download, and the submission steps live on [Co-branded debit card design](https://docs.ur.app/design/cards/co-branded-debit-card-design).

## Next steps

Once you have chosen one option from each, proceed to the detailed integration guide for your Account Mode:

* [Managed Custody Mode integration guide](/integration-methods/managed-custody-mode.md)
* [External Wallet Access Mode integration guide](/integration-methods/external-wallet-access-mode.md)

For card integration:

* **Fiat Only:** uses the standard Card endpoints in your Account Mode API reference (no separate integration surface).
* **Crypto Backed:** has a [dedicated API reference](https://docs.ur.app/api-reference/cards/crypto-backed-card) that plugs into either Account Mode.

For KYC details beyond integration mechanics:

* [KYC & compliance](/concepts/kyc-and-compliance.md) covers the full verification process, data collected, and status outcomes.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ur.app/getting-started/integration-guide.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
