# API Reference: Delegated Contract Mode

## API Configurations

### Base URLs

The API is deployed across different environments. Please use the appropriate base URL for your integration stage .

<table><thead><tr><th>Environment</th><th>Base URL</th></tr></thead><tbody><tr><td><strong>Testnet</strong></td><td><pre><code><strong>https://uropenapi-qa.ur-inc.xyz
</strong></code></pre></td></tr><tr><td><strong>Production</strong></td><td><code>https://openapi.ur.app</code></td></tr></tbody></table>

### API Authentication

The authentication method for the following Core Banking APIs refers to [this document](/developer-resources/signature-and-verify.md#part-a-partner-authentication-ur-open-api-and-webhooks).

## **User Onboarding Process**

### **Authorization URL Construction**

Partner **directly constructs** the authorization URL without needing to call an API beforehand. When users click the link, they will enter the UR authorization page to complete identity verification and authorization.

**Authorization URL Format**

```
https://get.ur.app/auth/authorize?partner_id={partner_id}&redirect_uri={callback_url}&scope={scopes}&state={custom_state}&response_type=code
```

**URL Parameter Description**

| Parameter       | Required | Description                                                                                                                                                        | Example                                                                                                              |
| --------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
| `partner_id`    | Yes      | ID generated by UR for the Partner                                                                                                                                 | `""`                                                                                                                 |
| `redirect_uri`  | Yes      | Callback address after authorization completion, must be pre-registered with UR                                                                                    | `https://partner.com/callback`                                                                                       |
| `scope`         | No       | Requested permission scopes, multiple scopes separated by spaces (URL encoding required)                                                                           | `allowance.mantle.USDC%20allowance.mantle.USD24`                                                                     |
| `state`         | No       | Partner custom state parameter for CSRF attack prevention and business information tracking. UR doesn't parse this value, only returns it as-is during redirection | `A random string you provide to verify against CSRF attacks. The length of this string can be up to 500 characters.` |
| `response_type` | Yes      | Fixed value: `code` (authorization code mode)                                                                                                                      | `code`                                                                                                               |

**Key Design**

* **No need to call API beforehand**: Partner directly constructs URL, reducing integration complexity
* **partner\_id**: UR identifies Partner through `partner_id` and confirms identity through signature when verifying code later
* **state is completely customizable**: Random string to prevent CSRF
* **Similar to standard authorization flow**: Developers don't need to learn a new authorization pattern

### **Available Scopes**

| Scope                    | Description                        |
| ------------------------ | ---------------------------------- |
| `allowance.mantle.USDC`  | USDC authorization on Mantle chain |
| `allowance.mantle.USD24` | USD authorization on Mantle chain  |
| `allowance.mantle.EUR24` | EUR authorization on Mantle chain  |
| `allowance.mantle.CHF24` | CHF authorization on Mantle chain  |
| `allowance.mantle.CNH24` | CNH authorization on Mantle chain  |
| `allowance.mantle.SGD24` | SGD authorization on Mantle chain  |
| `allowance.mantle.HKD24` | HKD authorization on Mantle chain  |
| `allowance.mantle.JPY24` | JPY authorization on Mantle chain  |
| `allowance.bsc.USDC`     | USDC authorization on BSC chain    |
| `card`                   | Card issuance                      |

### **User Completes Authorization**

After the user clicks the authorization link, they will enter the UR authorization page to complete KYC and authorization operations. After authorization is complete, UR will redirect back to the Partner's `redirect_uri` with the authorization code `code` and `state` parameters.

**Redirect URL Format**

```
{redirect_uri}?code={authorization_code}&state={original_state}
```

**Parameter Description**

| Parameter | Description                                                                                                     | Example                    |
| --------- | --------------------------------------------------------------------------------------------------------------- | -------------------------- |
| `code`    | Authorization code, Partner uses this code to exchange for user information (one-time use, valid for 5 minutes) | `UAC_a1b2c3d4e5f6g7h8i9j0` |
| `state`   | Returns the `state` parameter provided by Partner in step one as-is                                             | `""`                       |

**Redirect Example**

Assuming the Partner set `redirect_uri` to `https://partner.example.com/oauth/callback` in step one, after the user completes authorization, the browser will redirect to:

```
https://partner.example.com/oauth/callback?code=UAC_a1b2c3d4e5f6g7h8i9j0&state={state}
```

**Partner Callback Handling Example**

```javascript
// Partner's callback endpoint GET /oauth/callback
app.get('/oauth/callback', (req, res) => {
  const { code, state } = req.query;

  // 1. Verify state parameter to prevent CSRF attacks
  const stateData = JSON.parse(decodeURIComponent(state));
  console.log("Business information:", stateData);
  // { sourceId: 'mobile-app', campaign: 'spring-2024', userId: 'internal-user-12345' }

  // 2. Use code to call UR API to exchange for user information (see step three)
  // ...

  res.send("Authorization successful, processing...");
});
```

### **Partner to Fetch User Onboarding Information**

After receiving the authorization code `code`, Partner calls the UR API to exchange for the user's UR identity and authorization information. This step requires **Ethereum signature verification of Partner identity**. For detailed signing and verification rules, please refer to [Signature and Verification](/developer-resources/signature-and-verify.md).

**Field Description**:

* `userId`: UR user ID
* `userAddress`: User's Ethereum address
* `scope`: Granted permission scopes
* `state`: Returns the state parameter provided by Partner as-is
* `authorizedAt`: Authorization completion timestamp (Unix timestamp)

**Error Response**:

```json
{
  "code": 4001,
  "message": "Invalid or expired authorization code",
  "data": null
}
```

### Public Data Structures

#### TransactionData

Transaction data structure used in `/v1/transactions`, `/v1/transaction/query`, and `webhook.event.transaction`.

**Complete Example** (based on actual API response):

```json
{
  "urId": "7639951412",
  "title": "usd",
  "subtitle": "eip155:5003 USDC 12",
  "amount": "+11.94",
  "type": "CTU",
  "timestamp": 1768659501,
  "image": "",
  "currency": "usd",
  "direction": "IN",
  "txHash": "0x21b4dfa7be02b4e806cf8bc5469ef6af35c76afa6fbace2826c9f8afb2e06cc6",
  "inputChainId": "eip155:5003",
  "inputToken": "USDC",
  "inputAmount": "12",
  "inputTokenAddress": "0xe6a2802837da44f880f52c1681b6740db208755c",
  "outputAmount": "",
  "mcc": 0,
  "reference": "",
  "status": "",
  "bankAccount": "",
  "crdMultiToken": null,
  "ctuExternalSender": "0x96e023fb9b446a65273a0c01cdafdf26b5f21b3f",
  "token": "",
  "tokenAddress": "",
  "fromAddress": "",
  "toAddress": "",
  "statusCode": "",
  "crdCurrency": "",
  "listingTitle": "",
  "txHashUrl": "https://sepolia.mantlescan.xyz/tx/0x21b4dfa7be02b4e806cf8bc5469ef6af35c76afa6fbace2826c9f8afb2e06cc6",
  "txIdIcon": "",
  "officialName": "",
  "partnerRefId": ""
}
```

**Field Descriptions**:

| Field               | Type   | Required | Description                                                                                                                                                                                                    |
| ------------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `urId`              | string | Yes      | UR user ID (string format)                                                                                                                                                                                     |
| `title`             | string | Yes      | Transaction title (for display)                                                                                                                                                                                |
| `subtitle`          | string | Yes      | Transaction subtitle (e.g., counterparty UR ID, merchant name, chain info, etc.)                                                                                                                               |
| `amount`            | string | Yes      | Transaction amount (**display format with decimals**, e.g., `"+11.94"`), with sign indicating direction                                                                                                        |
| `type`              | string | Yes      | Transaction type abbreviation: CTU (cross-chain transfer in), FRX (forex exchange), CTF (crypto transfer), ONR (onramp), CRD (card payment), CDP (deposit), CWP (withdrawal), CWD (withdrawal refund), UNKNOWN |
| `timestamp`         | int64  | Yes      | Transaction timestamp (Unix seconds)                                                                                                                                                                           |
| `image`             | string | No       | Transaction display icon URL or card logo                                                                                                                                                                      |
| `currency`          | string | Yes      | Currency identifier (lowercase format, e.g., `"usd"`, `"eur"`)                                                                                                                                                 |
| `direction`         | string | Yes      | Transaction direction: `IN` (credit) / `OUT` (debit)                                                                                                                                                           |
| `txHash`            | string | Yes      | On-chain transaction hash (0x prefix)                                                                                                                                                                          |
| `inputChainId`      | string | No       | Input chain ID (CAIP-2 format, e.g., `eip155:5003` for Mantle Sepolia testnet)                                                                                                                                 |
| `inputToken`        | string | No       | Input token symbol                                                                                                                                                                                             |
| `inputAmount`       | string | No       | Input amount (**integer string** in smallest on-chain unit, e.g., `"12"`)                                                                                                                                      |
| `inputTokenAddress` | string | No       | Input token contract address (lowercase with 0x prefix)                                                                                                                                                        |
| `outputAmount`      | string | No       | Output amount (for exchange transactions, smallest on-chain unit)                                                                                                                                              |
| `mcc`               | uint64 | No       | Merchant category code (card payment transactions only)                                                                                                                                                        |
| `reference`         | string | No       | Transaction reference number                                                                                                                                                                                   |
| `status`            | string | No       | Transaction status: pending/completed/rejected/unknown. Empty string if status is unknown or not applicable                                                                                                    |
| `bankAccount`       | string | No       | Bank account information                                                                                                                                                                                       |
| `crdMultiToken`     | array  | No       | Card payment multi-token deduction details (array of `{token: string, amount: string}`)                                                                                                                        |
| `ctuExternalSender` | string | No       | External sender address for cross-chain transfer-in transactions (lowercase with 0x prefix)                                                                                                                    |
| `token`             | string | No       | Token symbol                                                                                                                                                                                                   |
| `tokenAddress`      | string | No       | Token contract address                                                                                                                                                                                         |
| `fromAddress`       | string | No       | Sender address                                                                                                                                                                                                 |
| `toAddress`         | string | No       | Recipient address                                                                                                                                                                                              |
| `statusCode`        | string | No       | Detailed status code                                                                                                                                                                                           |
| `crdCurrency`       | string | No       | Card payment original currency                                                                                                                                                                                 |
| `listingTitle`      | string | No       | Display title                                                                                                                                                                                                  |
| `txHashUrl`         | string | No       | Blockchain explorer link                                                                                                                                                                                       |
| `txIdIcon`          | string | No       | Transaction icon URL                                                                                                                                                                                           |
| `officialName`      | string | No       | Official name                                                                                                                                                                                                  |
| `partnerRefId`      | string | No       | Partner custom reference ID (e.g., partner's order number)                                                                                                                                                     |

**Key Field Format Notes**:

* **`urId`**: Always returned as a string, not a number
* **`amount`**: Display format with sign and decimals (e.g., `"+11.94"`, `"-6.00"`)
* **`currency`**: Lowercase format (e.g., `"usd"`, `"eur"`, not `"USD"` or `"EUR"`)
* **`inputAmount`**: Integer string representing smallest on-chain unit (e.g., `"12"` for USDC means 0.000012 USDC with 6 decimals)
* **`txHashUrl`**: Complete blockchain explorer URL for the transaction
* **Optional fields**: May be empty string or omitted depending on transaction type

#### **Chain ID Reference**

The `chainId` field in API requests uses the CAIP-2 standard format `eip155:<chainId>`, supporting the following chains:

**Mantle Chain**:

* **Testnet**: `eip155:5003` (Mantle Sepolia Testnet)
* **Mainnet**: `eip155:5000` (Mantle Mainnet)

**BSC Chain**:

* **Testnet**: `eip155:97` (BSC Testnet)
* **Mainnet**: `eip155:56` (BSC Mainnet)

> **Important Notes**:
>
> * If `chainId` is not specified in the request, it defaults to Mantle chain
> * Cross-chain deposits (e.g., from BSC) require explicit `chainId` and `userAddress` parameters
> * CAIP-2 format example: `eip155:97` represents BSC Testnet (chain ID 97)

#### **Unified amount field description**

**Unified amount field description**: All amount-related request fields named `amount`, `minAmount`, `maxAmount`, `minUsdcOut`, `feeAmount`, `minAmountOut`, etc., use the **string** type and are converted to the smallest on-chain unit based on the token's `decimals` (integers only). For example, for USD (`decimals=2`), 5.00 should be sent as `"500"`; for USDC (`decimals=6`), 1.23 should be sent as `"1230000"`.

## Core Banking APIs

### **Mint UR NFT**

Refers to [this open API](/developer-resources/openapis.md#mint-urid).

### **Card**

Webview URL: `https://get.ur.app/partner-login?partnerId=[Your PartnerId]&feature=card`

By opening this URL, users can activate, view, and manage their card.

### **Profile**

Webview Url: `https://get.ur.app/partner-login?partnerId=[Your PartnerId]&feature=profile`

By logging in to this URL, users can view their personal information, including Name, IBAN, Address, Bank Name, and BIC/SWIFT.

![profile-demo](/files/Cxy1q4mYzVJdeBDdDdHT)

### **Bank Transfer**

Webview URL: `https://get.ur.app/partner-login?partnerId=[Your PartnerId]&feature=bank-transfer`

By opening this URL, users can initiate and manage bank transfers, including selecting the source account, entering the recipient's bank details, specifying the amount, and reviewing transfer history.

### **Fetch UR Account Information**

Refers to [this open API](/developer-resources/openapis.md#fetch-ur-account-information).

### Fetch UR Account Balance

Refers to [this open API](/developer-resources/openapis.md#fetch-ur-account-balance).

### Get Supported Asset List

**Endpoint: GET /v1/tokens**

Partners can fetch the token list currently configured by UR for this partner (including on-chain precision and display precision), synchronized in real time with on-chain `chaincontractconfig`.

**Request Parameters**: None (GET request, no request body required).

**Response Example**:

```json
{
  "code": 0,
  "message": "",
  "data": [
    {
      "symbol": "USD",
      "name": "USD24",
      "address": "0xdf79470986629ae4893BfCE0c6C0F4d085E99741",
      "decimals": 2,
      "displayDecimals": 2,
      "isFiat": true
    },
    {
      "symbol": "USDC",
      "name": "USD Coin",
      "address": "0xe6a2802837da44F880f52c1681b6740db208755C",
      "decimals": 6,
      "displayDecimals": 2,
      "isFiat": false
    }
  ]
}
```

**Response Field Description**:

* `symbol`: Token symbol
* `name`: Token full name
* `address`: Token contract address
* `decimals`: On-chain smallest unit precision (`10^decimals`)
* `displayDecimals`: Recommended frontend display precision (can differ from `decimals`, e.g., 6 on-chain, 2 for display)
* `isFiat`: Whether it's a fiat token
* Token order follows on-chain configured `priority`, alphabetically by symbol if priority is the same.

### Fetch Currency Exchange Rate

**POST /v1/exchangeRate**

Get the exchange rate for the given asset pair.

**Request Parameters**:

```json
{
  "inSymbol": "EUR",
  "outSymbol": "USD"
}
```

| Field       | Type   | Required | Description  |
| ----------- | ------ | -------- | ------------ |
| `inSymbol`  | string | Yes      | Input token  |
| `outSymbol` | string | Yes      | Output token |

**Response Example**:

```json
{
  "code": 0,
  "message": "",
  "data": {
    "rate": "0.998",
    "exchangeSpread": "0.002"
  }
}
```

**Response Field Description**:

* `rate`: Exchange rate
* `exchangeSpread`: Exchange rate spread

### **Currency Exchange**

**POST /v1/exchange**

User exchange endpoint.

**Request Parameters**:

```json
{
  "urId": 12345,
  "inputToken": "USD",
  "outputToken": "EUR",
  "amount": "10000",
  "requestId": "req-20240101-0001"
}
```

| Field         | Type   | Required | Description                                                                  |
| ------------- | ------ | -------- | ---------------------------------------------------------------------------- |
| `urId`        | int64  | Yes      | UR user ID                                                                   |
| `inputToken`  | string | Yes      | Input token, use `symbol` returned by `/v1/tokens`                           |
| `outputToken` | string | Yes      | Output token, use `symbol` returned by `/v1/tokens`                          |
| `amount`      | string | Yes      | Exchange amount, on-chain smallest unit string (e.g., 100.00 USD => `10000`) |
| `requestId`   | string | Yes      | Request idempotency ID (client-defined, for idempotency and troubleshooting) |

**Response Example**:

```json
{
  "code": 0,
  "message": "",
  "data": {
    "txHash": "0x1234567890abcdef..."
  }
}
```

**Response Field Description**:

* `txHash`: Transaction hash

### Fetch Transaction History

Refers to [this open API](/developer-resources/openapis.md#fetch-transaction-history).

### Fetch Offramp Quote

**POST /v1/deposit/quote**

Returns fees, exchange rates, and estimated receipt amount for Fiat deposit scenarios. The current version supports direct deposits of Mantle-chain `USDC` to fiat tokens (`USD`, `EUR`, `CHF`, etc.).

**Request Parameters**:

```json
{
  "urId": 12345,
  "fromToken": "USDC",
  "toToken": "USD",
  "amount": "3000000",
  "chainId": "eip155:97",
  "userAddress": "0x1234567890abcdef..."
}
```

| Field         | Type   | Required | Description                                                                                                                                       |
| ------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `urId`        | int64  | Yes      | UR user ID                                                                                                                                        |
| `fromToken`   | string | Yes      | Input token symbol (currently only supports `USDC`), available `symbol` can be obtained from `/v1/tokens`                                         |
| `toToken`     | string | Yes      | Target tiat token (`USD`, `EUR`, etc.), use `symbol` returned by `/v1/tokens`                                                                     |
| `amount`      | string | Yes      | Input amount in smallest on-chain unit (USDC has 6 decimals: `3000000` = 3 USDC). **Minimum: 3 USDC**                                             |
| `chainId`     | string | No       | Source chain ID in CAIP-2 format (e.g., `eip155:5003` for Mantle Sepolia, `eip155:97` for BSC Testnet). Defaults to Mantle chain if not specified |
| `userAddress` | string | No       | User's UR account address (required when the user deposits from non-Mantle chains)                                                                |

**Response Example**:

```json
{
  "code": 0,
  "message": "",
  "data": {
    "quoteId": "deposit_1700000000000_12345",
    "feeAmountViaUsdc": "0.50",
    "outputAmount": "999.50",
    "outputAmountBeforeFee": "1000.00",
    "exchangeRate": "1.0",
    "crossChainFee": "0",
    "best": {
      "aggregator": "ur",
      "to": "0x...",
      "swapCalldata": "0x",
      "minUsdcAmount": "990000",
      "expectedUsdcAmount": "1000000",
      "slippageBps": 50,
      "deadline": 1703123600,
      "priceImpact": "0"
    },
    "feeAmountViaNativeToken": "0",
    "processingFee": "0.50",
    "networkFee": "0",
    "totalFee": "0.50",
    "allQuotes": [],
    "chainId": "eip155:5000"
  }
}
```

**Response Field Description**:

| Field                     | Type   | Description                                                                                                          |
| ------------------------- | ------ | -------------------------------------------------------------------------------------------------------------------- |
| `quoteId`                 | string | Quote ID, pass this to `/v1/deposit` to lock in the quoted fees                                                      |
| `feeAmountViaUsdc`        | string | Network gas fee (USDC denominated, decimal string, e.g., `0.05` means 0.05 USDC)                                     |
| `outputAmount`            | string | Final amount user will receive in target token (decimal string, after all fees and spread)                           |
| `exchangeRate`            | string | Exchange rate from input `fromToken` to `toToken`                                                                    |
| `crossChainFee`           | string | Cross-chain LayerZero fee in native token's smallest unit (e.g., wei for ETH, only applicable for non-Mantle chains) |
| `feeAmountViaNativeToken` | string | Fee in native token                                                                                                  |
| `processingFee`           | string | Processing fee                                                                                                       |
| `networkFee`              | string | Network fee                                                                                                          |
| `totalFee`                | string | Total fee                                                                                                            |
| `chainId`                 | string | Chain ID                                                                                                             |
| `allQuotes`               | array  | All available quotes. If it is USDC, ignore this field.                                                              |
| `best`                    | object | Best quote details. If it is USDC, ignore this field.                                                                |

> **Important Notes**:
>
> * `amount` must be at least **3 USDC** (3000000 in smallest unit)
> * The actual output amount deducts multiple fees: network fee (\~0.05 USDC), processing fee (\~0.5% of deposit), and spread adjustment
> * For cross-chain deposits (BSC, etc.), `crossChainFee` shows the LayerZero bridge fee in native token units
> * If `amount` is below minimum or `toToken` is not configured on-chain, error code 20003 will be returned

### Create Offramp Request

**POST /v1/deposit**

User deposit endpoint.

**Request Parameters**:

```json
{
  "urId": 12345,
  "inputToken": "USDC",
  "outputToken": "USD",
  "amount": "3000000",
  "requestId": "deposit-202401010001",
  "quoteId": "deposit_1700000000000_12345",
  "chainId": "eip155:97",
  "userAddress": "0x1234567890abcdef..."
}
```

| Field         | Type   | Required | Description                                                                                                                                 |
| ------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `urId`        | int64  | Yes      | UR user ID                                                                                                                                  |
| `inputToken`  | string | Yes      | Input token (only supports `USDC`), available `symbol` can be obtained from `/v1/tokens`                                                    |
| `outputToken` | string | Yes      | Output token (fiat token), use `symbol` returned by `/v1/tokens`                                                                            |
| `amount`      | string | Yes      | Deposit amount in smallest on-chain unit (e.g., 3 USDC = `3000000`). **Minimum: 3 USDC**                                                    |
| `requestId`   | string | Yes      | Idempotent request ID, must remain the same on retry                                                                                        |
| `quoteId`     | string | Yes      | Quote ID returned by `/v1/deposit/quote`.                                                                                                   |
| `chainId`     | string | No       | Source chain ID in CAIP-2 format (e.g., `eip155:5003` for Mantle Sepolia, `eip155:97` for BSC Testnet). Defaults to Mantle if not specified |
| `userAddress` | string | No       | User's wallet address (required for cross-chain deposits from non-Mantle chains)                                                            |

**Response Example**:

```json
{
  "code": 0,
  "message": "",
  "data": {
    "txHash": "0x1234567890abcdef..."
  }
}
```

**Response Field Description**:

* `txHash`: Transaction hash

> **Important Notes**:
>
> * `requestId` must be globally unique and reused on retry to ensure idempotency
> * `amount` must be at least **3 USDC** (3000000 in smallest unit)
> * Currently supports `USDC → Fiat token` deposits from Mantle and BSC chains
> * For BSC deposits, `userAddress` is required for cross-chain fee calculation
> * **Recommended**: Always call `/v1/deposit/quote` first and pass the returned `quoteId` to lock in the quoted fees. When `quoteId` is provided, the server validates that `urId`, `inputToken`, `outputToken`, and `amount` match the original quote — any mismatch will be rejected. If the quote has expired, request a new one
> * When `quoteId` is omitted, the deposit is processed without fee deduction (backward-compatible behavior).

### **Create Onramp Request**

**POST /v1/onramp**

Exchanges a fiat token to USDC and (optionally) performs a swap/bridge to the target token based on the quote from `/v1/onramp/quote`.

**Request Parameters**

```json
{
  "quoteId": "onramp_1700000000000000000",
  "requestId": "onramp-demo-001",
  "urId": 7639951412,
  "chainId": "eip155:5000",
  "tokenIn": "USD",
  "amountIn": "10000",
  "withdrawAddress": "0xUserWithdrawAddress",
  "dstChainId": "eip155:8453",
  "dstAggregator": "0xAggregatorAddress",
  "dstTokenOut": "USDC",
  "dstSwapCalldata": "0xabcdef...",
  "dstMinAmountOut": "99000000"
}
```

| Field             | Type   | Required | Description                                                                           |
| ----------------- | ------ | -------- | ------------------------------------------------------------------------------------- |
| `quoteId`         | string | Yes      | Quote ID returned by `/v1/onramp/quote`                                               |
| `requestId`       | string | Yes      | Idempotent request ID, reuse on retry                                                 |
| `urId`            | int64  | Yes      | UR user ID                                                                            |
| `tokenIn`         | string | Yes      | Fiat token symbol, use `symbol` returned by `/v1/tokens`                              |
| `amountIn`        | string | Yes      | Input amount (smallest unit). **After BufferPool quote conversion, must be ≥ 5 USDC** |
| `withdrawAddress` | string | No       | User-specified withdrawal address for onramp                                          |
| `chainId`         | string | No       | Source chain ID, e.g. `eip155:5000` (currently Mantle only)                           |
| `dstChainId`      | string | No       | Destination chain ID for bridge/swap, e.g. `eip155:8453`                              |
| `dstAggregator`   | string | No       | Aggregator contract address, use `best.aggregator` from quote                         |
| `dstTokenOut`     | string | No       | Destination token symbol                                                              |
| `dstSwapCalldata` | string | No       | Swap calldata, use `best.swapCalldata` from quote                                     |
| `dstMinAmountOut` | string | No       | Minimum acceptable USDC amount (smallest unit), use `best.minUsdcAmount` from quote   |

**Response Example**

```json
{
  "code": 0,
  "message": "",
  "data": {
    "txHash": "0x1234567890abcdef..."
  }
}
```

**Description**

* Returns `txHash` on success, transaction details can be queried via `/v1/transactions`.
* `dstAggregator`, `dstSwapCalldata`, `dstMinAmountOut` should come from the latest `/v1/onramp/quote` response.
* If no swap/bridge is needed, omit all `dst*` fields to perform only fiat token → USDC.

### **Fetch Onramp Quote**

**POST /v1/onramp/quote**

Returns a real-time quote for fiat token → USDC (with optional swap/bridge info) based on BufferPool and limit rules.

**Request Parameters**

```json
{
  "urId": 7639951412,
  "chainId": "eip155:5000",
  "fromToken": "USD",
  "toToken": "USDC",
  "amount": "10000",
  "slippageBps": 50
}
```

| Field         | Type   | Required | Description                                                                           |
| ------------- | ------ | -------- | ------------------------------------------------------------------------------------- |
| `urId`        | int64  | Yes      | UR user ID                                                                            |
| `fromToken`   | string | Yes      | Fiat token symbol, use `symbol` returned by `/v1/tokens`                              |
| `toToken`     | string | Yes      | Destination token symbol, use `symbol` returned by `/v1/tokens`                       |
| `amount`      | string | Yes      | Input amount (smallest unit). **After BufferPool quote conversion, must be ≥ 5 USDC** |
| `slippageBps` | int32  | No       | Slippage in bps, default 50                                                           |
| `chainId`     | string | No       | Chain ID, e.g. `eip155:5000` (currently Mantle only)                                  |

**Response Example**

```json
{
  "code": 0,
  "message": "",
  "data": {
    "quoteId": "onramp_1700000000000000000",
    "chainId": "eip155:5000",
    "best": {
      "aggregator": "0xAggregatorAddress",
      "to": "0xAggregatorTarget",
      "swapCalldata": "0xabcdef...",
      "minUsdcAmount": "99500000",
      "expectedUsdcAmount": "99800000",
      "slippageBps": 50,
      "deadline": 1700000000,
      "priceImpact": "0.0012"
    },
    "allQuotes": [
      {
        "source": "aggregatorA",
        "expectedUsdcAmount": "99800000",
        "priceImpact": "0.0012"
      }
    ],
    "isSupport": true,
    "needLivenessCheck": false,
    "outputAmount": "99800000",
    "exchangeRate": "0.9995",
    "crossChainFee": "0",
    "feeAmountViaUsdc": "500000",
    "feeAmountViaNativeToken": "0",
    "maxAmounts": {
      "USD": "50000",
      "EUR": "46500"
    },
    "livenessCheckUrl": "https://example.com?token=xxx&partnerId=7639951412"
  }
}
```

**Response Field Description**

| Field                     | Type   | Description                                                                                                                                                                                                                                                                                                                                                                                    |
| ------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `quoteId`                 | string | Quote ID                                                                                                                                                                                                                                                                                                                                                                                       |
| `chainId`                 | string | Chain ID                                                                                                                                                                                                                                                                                                                                                                                       |
| `best`                    | object | Best quote details, see `OnrampBestQuote`                                                                                                                                                                                                                                                                                                                                                      |
| `allQuotes`               | array  | Aggregator quotes list, see `OnrampAltQuote`                                                                                                                                                                                                                                                                                                                                                   |
| `feeAmountViaUsdc`        | string | Fee amount denominated in USDC (smallest unit)                                                                                                                                                                                                                                                                                                                                                 |
| `outputAmount`            | string | Final output amount (smallest unit)                                                                                                                                                                                                                                                                                                                                                            |
| `exchangeRate`            | string | Effective exchange rate after fee deduction                                                                                                                                                                                                                                                                                                                                                    |
| `crossChainFee`           | string | Cross-chain fee (smallest unit)                                                                                                                                                                                                                                                                                                                                                                |
| `feeAmountViaNativeToken` | string | Fee amount denominated in native token (smallest unit)                                                                                                                                                                                                                                                                                                                                         |
| `isSupport`               | bool   | Whether the current UR ID is allowed to continue onramp (based on liveness status, region restrictions, USDC de-peg checks, etc.)                                                                                                                                                                                                                                                              |
| `needLivenessCheck`       | bool   | **Facial verification trigger**: Indicates whether the current transaction requires a biometric liveness check (for example, a facial scan) before processing. This is dynamically determined by UR's risk engine based on the user's profile and requested onramp amount. If `true`, the frontend must guide the user through the verification flow.                                          |
| `maxAmounts`              | object | The maximum allowable input value for a single transaction. Any input exceeding this threshold will result in a transaction failure. Important: This limit is enforced strictly by risk control rules and is independent of the user's `available` monthly limit. Users may have sufficient monthly allowance but still be restricted by this single-transaction cap due to security policies. |
| `livenessCheckUrl`        | string | Liveness check URL (only when `isSupport && needLivenessCheck`)                                                                                                                                                                                                                                                                                                                                |

**OnrampBestQuote**

| Field                | Type   | Description                                 |
| -------------------- | ------ | ------------------------------------------- |
| `aggregator`         | string | Aggregator name/address                     |
| `to`                 | string | Target contract address                     |
| `swapCalldata`       | string | Swap calldata                               |
| `minUsdcAmount`      | string | Minimum USDC output amount (smallest unit)  |
| `expectedUsdcAmount` | string | Expected USDC output amount (smallest unit) |
| `slippageBps`        | int32  | Slippage in bps                             |
| `deadline`           | int64  | Quote deadline timestamp                    |
| `priceImpact`        | string | Price impact                                |

**OnrampAltQuote**

| Field                | Type   | Description                                 |
| -------------------- | ------ | ------------------------------------------- |
| `source`             | string | Aggregator source                           |
| `expectedUsdcAmount` | string | Expected USDC output amount (smallest unit) |
| `priceImpact`        | string | Price impact                                |

> **Note**: If `isSupport = false`, guide the user to try again later or complete the required liveness verification.

### **Fetch Transaction Details**

Refers to [this open API](/developer-resources/openapis.md#fetch-transaction-details).

## Webhooks

Webhook definitions are centralized in [Webhooks](/developer-resources/webhook.md). For delegated contract mode, the relevant events are `transaction` and `allowance`.

## Environment

```sepolia
# sepolia
url: 

# auth sepolia
https://ur-fe-tob.qa4.gomantle.org/auth/authorize?state=1&partner_id={partner_id}&redirect_uri={redirect_uri}&response_type=code&scope=allowance.mantle.USDC%20allowance.mantle.USD24%20allowance.mantle.EUR24

# card url
https://ur-fe-tob.qa4.gomantle.org/partner-login?partnerId=90001&feature=card
```

```mainnet
# mainnet
url: https://openapi.ur.app

# auth 
https://get.ur.app/auth/authorize?state=1&partner_id={partner_id}&redirect_uri={redirect_uri}&response_type=code&scope=allowance.mantle.USDC%20allowance.mantle.USD24%20allowance.mantle.EUR24

# card url
https://get.ur.app/partner-login?partnerId={partnerId}&feature=card


```

## Partner Configuration Required

```
signerAddress: Partner signing publicAddress
webhookUrl: URL to receive Webhook notifications
url: Web redirect URL (partner page linked from UR authorization page)
redirectDomain: Allowed auth redirect domains, multiple values supported for testing

```

> Additional notes:
>
> * Both environments have identical signature/authentication logic, differences only in on-chain data and chain ID, choose Base URL as needed.
> * For QA, staging, or dedicated environments, please contact UR representative to obtain independent domain and public key.

## Frequently Asked Questions (FAQ)

#### Authorization Flow Related

**Q: How long is the authorization code valid?**

A: Authorization codes are valid for 5 minutes by default and are single-use. Partners should call `/v1/profile` immediately after receiving the code to exchange for user information.

**Q: What happens if the user denies authorization?**

A: UR will redirect back to `redirect_uri` with an `error` parameter:

```
https://partner.com/callback?error=access_denied&error_description=User+denied+authorization&state=xxx
```

**Q: Must redirect\_uri be pre-registered?**

A: Yes. For security, partners must pre-register all possible `redirect_uri` URLs in the UR system. During authorization, UR will verify if the `redirect_uri` in the URL is on the whitelist.

***

## Error Code Description

| Error Code | Description                                                                               | Solution                                                                           |
| ---------- | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| 10001      | Invalid request signature (`ErrSignatureInvalid`)                                         | Check signature algorithm, deadline, and whether private key is correct            |
| 20001      | Request body is empty or missing required fields (`ErrReqBodyEmpty`)                      | Ensure request body is valid JSON and includes required fields                     |
| 20002      | Request body parsing failed (`ErrParseRequestFailed`)                                     | Check JSON format, encoding, and Content-Type                                      |
| 20003      | Invalid parameter (`ErrInvalidParam`), common in `amount` format, token name, urId errors | Adjust parameters based on error message, follow smallest unit string requirements |
| 30001      | NFT already exists (`ErrNFTIdExists`)                                                     | NFT already exists in DB or on-chain, use existing Token ID                        |
| 50001      | Server failed to read request (`ErrIoRead`)                                               | Typically network read/write exception, can retry                                  |
| 50002      | Internal error (`ErrInternal`)                                                            | UR internal service exception, retry later or contact UR support                   |
| 50003      | On-chain or external service exception (`ErrChainRpc`)                                    | Chain RPC or third-party service failure, can retry later                          |


---

# Agent Instructions: 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:

```
GET https://docs.ur.app/developer-resources/api-reference-delegated-contract-mode.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
