For the complete documentation index, see llms.txt. This page is also available as Markdown.

API reference: External Wallet Access

Complete API reference for partners integrating via External Wallet Access.

1. Overview

The UR API consists of two distinct services hosted on independent domains: UR-API (UR's private API) and UR-OPEN-API (Open API for third parties).

  • UR-API: Provides functionalities for User Registration, KYC Verification, Crypto Deposits, Foreign Exchange (FX), and Crypto On/Off Ramps.

  • UR-OPEN-API: Provides Third-party Authentication, Corporate (B-side) Minting, and Corporate Transaction History queries.

Sections 1.1 and 1.2 introduce the base information and authentication methods for UR-API (Client-side). Section 8 introduces the base information and authentication methods for UR-OPEN-API (Partner-side).

1.1 API Base Information

Base URLs

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

Environment
Base URL

Testnet

https://urapi3-qa.ur-inc.xyz

Preview

https://api2-preview.ur.app

Production

https://api.ur.app

Authentication Method: Header Authentication

All API requests must include the following specific headers for authentication and verification .

Header Field
Type
Required
Description

tokenId

string

Yes

User's URID

network

string

Yes

The blockchain network identifier.

sign

string

Yes

The cryptographic signature from the user.

hash

string

Yes

The hash of the original request data.

deadline

string

Yes

The expiration timestamp for the request.

Field Definitions :

  • tokenId: The User's URID.

  • network: Use 5000 for Mainnet and 5003 for Testnet.

  • sign: The signature generated by the user's wallet.

  • hash: The SHA3/Keccak256 hash of the original request payload.

  • deadline: Server timestamp + validity window (max 20 minutes). This is controlled by the partner to ensure signature validity.

Data Format

  • Format: JSON

Universal Response Format

All API responses follow this standard JSON structure :

1.2 Signature and Verify

UR APIs are categorized into three authentication levels based on data sensitivity and operation type. For a complete guide on signature formats and verification logic for both Partners and Users, please refer to Signature and Verification.

A. No Auth (Public Interfaces)

  • Scenarios: Querying public information such as supported countries, UR server timestamp, exchange rates, or OTP login.

  • Method: No authentication information is required in the request.

B. Basic Auth

Scenarios: Operations that do not involve fund movements but require basic user identification, such as User Registration (Minting) or generating tokens. Method: The request must include the tokenId(User's URID) in the Header.

C. Full Auth

  • Scenarios: Operations involving fund movements or sensitive data where every call requires a user signature to prevent replay attacks. Examples include Currency Exchange (FX), Permit, and querying Transaction History.

Note: In the following documentation, every API will indicate its specific Authentication Level. Callers must strictly adhere to these levels. Additionally, some interfaces may have specific requirements regarding the User Status.

2. Account

This section covers API endpoints and webhooks related to user account management.

2.1 Account API

2.1.1 Get Server Timestamp

1. Description Retrieves the current server timestamp from the UR service. This timestamp is required for calculating the signature deadline.

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v1/timestamp

Auth Level

No Auth

Headers

Content-Type

Fixed: application/json

|

3. Response

4. Request Example

5. Error Codes

2.1.2 Email Verification

1. Description Checks if the user's email address is available for registration. If the email is unavailable, the interface returns an error message, and the user must provide a different email to open an account.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v2/email-status

Auth Level

No Auth

Request Parameters

3. Response

Scenario: Email already exists (Unavailable)

Scenario: Email is available (Success)

4. Request Example

5. Error Codes

2.1.3 Get User Status

1. Description Retrieves detailed status information of the user account, including account status, KYC process progress, SumSub KYC info, and novice guidance progress .

Scenarios:

  • Query account status after user login.

  • Determine accessible features based on current status.

  • Display the current progress of the KYC verification flow.

  • Track novice guidance completion.

  • Determine if the user needs to complete specific verification steps .

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v2/account-status

Auth Level

Basic Auth

No status restriction

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier

3. Response

Success Response (HTTP 200):

**result Field Breakdown:

Field Name
Type
Description

status

int

Account status code (0=Na, 1=SoftBlocked, 2=Tourist, 3=Blocked, 4=Closed, 5=Live)

statusStr

string

Account status string ("Na", "SoftBlocked", "Tourist", "Blocked", "Closed", "Live".)

kycFlow

object

KYC flow information (see KycFlowResponse structure below)

sumsubKycInfo

object

SumSub KYC information (see SumsubKycInfo structure below)

noviceGuidanceProcessStep

int

Current step of novice guidance (0 indicates not started or unfinished; queried only in Live status)

noviceGuidanceProcessStepLatestTimeMs

int64

Latest update timestamp for novice guidance (milliseconds)

**KycFlowResponse Structure:

Field Name
Type
Description

currentStep

int

Current KYC step (0=UNKNOWN, 1=FormA, 2=IDScan, 3=SignFormA, 4=Review, 5=Rejected)

currentStepStr

string

Current step name ("FormA", "IDScan", "SignFormA", "Review", "Rejected")

currentStepActionTypes

string]

Action types required for the current step (e.g., ["sumsub"], ["sign"])

failReason

string

Reason for KYC failure (value exists only when currentStep is Rejected)

**SumsubKycInfo Structure:

Field Name
Type
Description

userId

string

SumSub Applicant ID, used for querying KYC status

latestKycHasCompleted

bool

Whether the latest KYC process has been completed

reviewStatus

string

Review status ("init", "pending", "prechecked", "completed", etc.)

reviewAnswer

string

Review result ("GREEN"=Passed, "RED"=Rejected)

reviewRejectType

string

Rejection type (e.g., "RETRY", "FINAL", etc.; value exists only when rejected)

**CrsInfo Structure:

Field Name
Type
Description

needCrs

bool

Indicates whether the user is required to complete the CRS process.

restrictDate

int64

Represents the deadline or restriction timestamp for completing the CRS process, usually in Unix timestamp format (milliseconds). After this time, the user may be softBlocked.

url

string

The CRS submission link that directs the user to the CRS information collection page.

Response Field Details (Status):

  • 0 (Na): New user, URID NFT not minted.

  • 1 (SoftBlocked): An ongoing task (CRS, ongoing KYC, or EDD) is overdue; money features are locked until it is completed.

  • 2 (Tourist): URID NFT minted, KYC not completed.

  • 3 (Blocked): Account frozen.

  • 4 (Closed): Account closed.

  • 5 (Live): KYC passed; all verifications complete, transactions enabled.

4. Request Example

5. Error Codes

Code
Type
Description
Solution

10001

Auth Failure

Invalid tokenId or user does not exist

Check if tokenId is correct and user is registered

10002

Parse Error

Missing or malformed Header parameters

Ensure valid tokenId and network Headers are provided

10009

Invalid Param

tokenId format error

Provide a valid NFT Token ID (positive integer)

10000

System Error

Database query failed or service exception

Retry later or contact technical support

2.1.4 MINT (Create User's URID)

Item
Value
Note

HTTP Method

POST

URI

/api/v1/mint

Auth Level

Basic Auth

User status must be Na (0)

Headers

Content-Type

Fixed: application/json

tokenId

Pre-generated URID (via generate-token interface)

network

Network Identifier (e.g., "mainnet")

Parameter
Type
Required
Description
Example

address

string

Yes

User's Ethereum wallet address.

"0x123..."

lotNumber

string

Yes

GeeTest verification session ID.

"7a8f..."

captchaOutput

string

Yes

GeeTest verification output result.

"XyZ123..."

passToken

string

Yes

GeeTest pass token.

"token_..."

genTime

string

Yes

GeeTest generation timestamp (seconds).

"1703123456"

image

string

No

NFT Image (Base64).

"data:image..."

backGroundColor

string

No

Background color (Hex).

"#FFFFFF"

land

string

No

Land information.

"land1"

Field
Type
Description

tokenId

string

User's URID

txHash

string

Blockchain transaction hash for tracking status.

Code
Type
Description
Solution

10002

Parse Error

Request parameter format error

Check JSON format and field types

10003

ID Not Found

Mint Token ID does not exist

Call /api/v1/generate-token first

10004

Mismatch

Token ID does not match address

Confirm TokenID relationship with wallet address

10005

Duplicate Mint

Address already has an NFT

Use existing Token ID

10007

Duplicate Mint

Token already used for minting

Same as 10005

10009

Invalid Param

Missing required fields

Check address, lotNumber, etc.

10010

GeeTest Fail

Verification failed or expired

Retry GeeTest verification

10006

Status Error

Account status is not Na

Check account status

Please refer to OpenAPI Mint for the URID minting.

2.1.5 Get Sumsub SDK Token

1. Description Creates an access token for SumSub KYC verification. This token is used to initialize the SumSub SDK (Web or Mobile) and start the identity verification process .

Call Scenarios:

  • When a user starts the KYC identity verification process.

  • When the frontend needs to initialize the SumSub SDK.

  • When the token expires during verification and needs refreshing.

  • During KYC retry scenarios (supporting various retry levels).

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v1/sumsub/create-access-token

Auth Level

Full Auth

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier

sign

Wallet Signature

hash

Original request hash

deadline

Signature deadline

Request Parameters

Parameter
Type
Required
Description
Example

userId

string

No

Optional. When omitted, the server derives the internal Sumsub user id from Full Auth context (e.g. tokenId). Only pass this if UR gave you an explicit pattern for your tenant.

"12345"

levelName

string

No

Specific SumSub Level name. Empty uses default.

"Basic information"

ttl

int

No

Token time-to-live (seconds). Default configured by server.

3600

isRetryVerification

bool

No

Indicates if this is a KYC retry scenario.

false

retryLevel

int32

No

Retry level (1-7), valid only if isRetryVerification=true.

1

stepType

string

No

Specific verification step to reset (e.g., "IDENTITY").

"IDENTITY"

failureReason

string

No

Reason for failure, used for logging.

"Document expired"

3. Response

Result Field Description

Field
Type
Description

token

string

SumSub Access Token (usually starts with "act-"). Used to initialize the SDK.

userId

string

SumSub Applicant ID, used for subsequent queries.

4. Request Example

You may include "userId": "…" in the JSON body only when UR instructs you to use a tenant-specific pattern.

5. Error Codes

Code
Type
Description
Solution

10002

Parse Error

Request parameter format error

Check JSON format and optional body fields

10009

Invalid Param

Invalid or inconsistent parameters

Verify headers and body per tenant guidance

10000

System Error

SumSub service exception

Retry later or contact support

2.1.6 Get User KYC Document (Form A)

1. Description Retrieves the content and structure of the KYC Form A (Client Due Diligence). This interface is called before the user signs Form A to display the declaration text that requires the user's signature . Form A is a critical KYC document containing compliance information such as financial status, source of funds, and account purpose.

Call Scenarios:

  • After the user completes SumSub verification, they must fill out/sign Form A.

  • The frontend retrieves the specific content to display to the user.

  • Retrieves the self-declaration text for the user to confirm via signature.

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v2/kyc/form-a-info

Auth Level

Full Auth

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier

sign

Wallet Signature

hash

Original request hash

deadline

Signature deadline

3. Response

Result Field Description

Field
Type
Description

kycSelfDec

string

The complete Form A text content retrieved from the SumSub system. Contains user personal info and compliance declarations. The user must read and sign this exact text.

4. Request Example

5. Error Codes

Code
Type
Description
Solution

10001

Auth Failure

Invalid tokenId or user does not exist

Check if tokenId is correct and user is registered

10002

Parse Error

Header parameters missing or malformed

Ensure valid tokenId and network Headers

10009

Invalid Param

tokenId format error

Provide valid NFT Token ID

10000

System Error

KYC Flow status incorrect or data exception

Check detailed error message

2.1.7 Submit User Signature (Submit Form A)

1. Description Submits the user's signature for the KYC Form A (Customer Due Diligence Form). After reading the Form A content, the user uses their wallet to sign the content and submits the signature via this interface to complete the final step of the KYC process.

Call Scenarios:

  • User has retrieved Form A content via /api/v2/kyc/form-a-info.

  • User reads and confirms the Form A content.

  • User uses the wallet to sign the Form A content.

  • Submit the signature to complete KYC certification .

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v2/kyc/submit-form-a

Auth Level

Full Auth

Header

Content-Type

Fixed: application/json

Header

tokenId

User's URID

Header

network

Network Identifier: 5000

Header

sign

Wallet Signature

Header

hash

Original request hash

Header

deadline

Signature deadline

Request Parameters

Parameter
Type
Required
Description
Example

kycSelfDec

string

Yes

Form A self-declaration text content. Must be exactly the same as the dec field returned by the form-a-info interface.

"I, John Doe, hereby declare..."

kycSelfDecSign

string

Yes

ECDSA signature of the Form A text by the user. (65-byte hex string).

"0x1234...abcd"

Parameter Notes:

  • kycSelfDec: Must include the complete Form A text content. Cannot be modified or truncated.

  • kycSelfDecSign:

  • Uses the user wallet's private key to sign kycSelfDec.

  • Format: 65-byte hexadecimal string (130 chars, starting with 0x).

  • Structure: r (32 bytes) + s (32 bytes) + v (1 byte).

  • Adopts standard EIP-191 (Ethereum Signed Message) mechanism.

  • Verification Logic: The backend will prefix the kycSelfDec text with \x19Ethereum Signed Message:\n<length>, calculate the Keccak256 hash, recover the public key address from the signature, and compare it with the current user's wallet address . Signature Generation Example (Frontend/JS):

3. Response

Response Description:

  • retCode: 0 indicates signature verification passed and saved successfully.

  • result: Empty JSON object {}.

  • Note: After returning success, wait for 3 seconds to allow downstream services to process the status update (interface has internal sleep) .

4. Request Example

5. Error Codes

Code
Error Type
Description
Solution

10001

Auth Failure

Invalid tokenId or user does not exist.

Check if tokenId is correct.

10002

Parse Error

JSON format error or parameter type mismatch.

Ensure kycSelfDec and kycSelfDecSign are both strings and JSON is valid.

10009

Invalid Param

Required fields missing or empty.

Ensure both kycSelfDec and kycSelfDecSign are provided.

10000

System Error

Signature verification failed, database error, or Kafka failure.

Check error message details (e.g., signature mismatch).

2.2 Account Webhook

Webhook definitions are centralized in Webhooks. For account-related events, see sumsub_kyc_result and kyc_status.

3. Card

This section covers API endpoints related to UR debit card management and banking operations.

3.1 Card API

3.1.1 Get User Profile

1. Description Retrieves the user's banking profile information, including IBAN, account holder name, supported currencies, billing address, and card eligibility status.

Call Scenarios:

  • Displaying account details and transaction limits to the user.

  • Checking if the user has already issued a card or is eligible to do so.

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v2/br

Auth Level

Full Auth

Requires wallet signature

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier (e.g., 5000)

sign

Wallet Signature

hash

Original request hash

deadline

Signature deadline

3. Response

Result Field Description

Field
Type
Description

br

string

Account Holder Name.

iban

string

User's IBAN (formatted with spaces).

country

string

ISO3 Country Code (e.g., "CHE" for Switzerland).

isCardEligible

boolean

Indicates if the user is eligible to issue a card.

cards

array

List of existing cards.

cardActivation

object

Activation fee info (Amount/Currency). Returned only if isCardEligible=true and cards is empty.

limits

object

The limits object defines the user's monthly spending capacity, denominated in CHF (Swiss Franc), within a rolling 30-day cycle.It consists of max, representing the total allowable limit allocated to the user , and used, which tracks the cumulative volume of all fiat-related operations (including FX, Card Spending, On-ramps, and Cash Payouts). The available balance is dynamically calculated as the difference between max and used.To ensure transaction success, partners must verify that any requested outgoing transaction amount does not exceed the available limit, as outgoing operations surpassing this threshold will automatically fail.

depositBank

object

Bank account details for topping up the account (grouped by currency). EUR and CHF use the default IBAN, issued automatically when the user reaches Live. USD uses a separate USD IBAN, issued only after you request it with POST /v1/apply-usd-payin (a synchronous call; UR creates the IBAN immediately if the user is Live).

contacts

object

The user's bank payout contact list.

4. Request Example

5. Error Codes

Code
Type
Description
Solution

10000

DefError

Default/Upstream Error

Check request parameters and system status.

10001

Auth Failure

Signature Verification Failed

Check headers, signature, deadline validity, and address match.

10002

Parse Error

Request Parsing Failed

Validate JSON format and Content-Type.

10006

Status Error

Account Status Not Supported

User account must be in a valid state (e.g., Live).

10016

Rate Limit

Too Many Requests

Retry later (exponential backoff).

10999

Blocked

Trade Blocked

Account restricted; contact support.

3.1.2 Create Card

1. Description: After passing KYC verification and meeting card issuance conditions, the user calls this interface to apply for a new virtual card. This process typically involves an initial top-up amount and currency specification.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v2/card

Auth Level

Full Auth

Requires wallet signature

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier (e.g., 5000/5003)

sign

Wallet Signature

hash

Original request hash

deadline

Signature deadline

3. Response

4. Request Example

5. Error Codes

Code
Type
Description
Solution

10000

DefError

Default error containing specific business error info

Return 400 (Parameter error or conditions not met), Unauthorized signature, or Service Internal Error.

3.1.3 Get Card Info

1. Description Retrieves card information and the cardToken. The cardToken is used to initialize the frontend component to securely display sensitive card details such as the CVV.

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v2/card

Auth Level

Full Auth

Requires wallet signature

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier (5000/5003)

sign

Wallet Signature

hash

Original request hash

deadline

Signature deadline

3. Response

4. Request Example

5. Error Codes

Code
Type
Description
Reason

10000

DefError

Default error containing specific business error info.

1. Request parameters error (unsupported currency, card not found/not created). 2. Unauthorized: Signature verification failed. 3. Service Internal Error. 4. Data parsing failed.

3.1.4 Get Card Details

The card API does not expose sensitive debit card data such as PAN, CVV, or expiry in JSON. Use cardToken only to render those sensitive fields through UR's card display script. The cardToken is short-lived and expires after 5 minutes. When it expires, call GET /api/v2/card again to get a fresh token.

Card identifiers:

Field
Use

cardToken

Short-lived token for card detail display only. Do not store or log it.

externalId

Stable card management ID. Use it for APIs such as Set Default Transaction Currency.

activeTokens[].id

Device wallet token ID, such as Apple Pay. Do not use it for card detail display or currency settings.

Load the script from UR:

Add DOM placeholders where the script should render sensitive fields:

Initialize the display after the user chooses to reveal card details:

Common mistakes:

  • Do not store or log cardToken.

  • Do not use activeTokens[].id unless calling a device-token management API.

  • Load the script only on the card details view or secure webview, not globally across your app.

  • Render card details only after explicit user action, such as selecting "Show card details".

3.1.5 Set Default Transaction Currency

1. Description Sets the default transaction currency for the user's card.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v2/card-currency

Auth Level

Full Auth

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier (5000/5003)

sign

Wallet Signature

hash

Original request hash

deadline

Signature deadline

Request Parameters

Parameter
Type
Description

cardExternalId

string

Stable card external ID returned by GET /api/v2/card as result.externalId.

currency

string

The default transaction currency to set, such as USD, EUR, or CHF.

3. Response

4. Request Example

Notes:

  • Use the stable externalId value returned by GET /api/v2/card.

5. Error Codes

Code
Type
Description
Solution

10000

DefError

Default error containing specific business error info.

1. Parameter errors (e.g., unsupported currency, card does not exist), 2. Signature verification failed 3. Upstream service error.

3.1.6 Get Transaction History

1. Description Retrieves the transaction history for the user's account. Supports date range filtering and pagination.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v2/transactions

Auth Level

Full Auth

Requires wallet signature

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier (e.g., 5000)

sign

Wallet Signature

hash

Original request hash

deadline

Signature deadline

Request Body

Parameter
Type
Required
Description

pageSize

int

No

Page size (default 50).

fromTimestamp

long

No

Start timestamp (Unix seconds).

toTimestamp

long

No

End timestamp (Unix seconds).

type

string

No

Single transaction type (e.g. P2P, FRX, CTU, CRD, CDP). Mutually exclusive with transactionTypes.

transactionTypes

string[]

No

Multiple transaction-type filter. Mutually exclusive with type.

currencys

string[]

No

Currency filter (e.g. EUR, USD, CHF, CNH).

direction

string

No

IN, OUT, or ALL.

minAmount / maxAmount

string

No

Amount range filter.

status

string

No

Transaction status filter.

chainId

string

No

e.g. eip155:5000.

tokenSymbol

string

No

e.g. USDC.

cursorTimestamp / cursorId

long

No

Forward-pagination cursor.

id / txHash

long / string

No

Query a single transaction (mutually exclusive).

3. Response

Result Field Description (each entry is a TransactionV2; fields are shared with TransactionData — see Delegated Contract Mode → TransactionData)

Field
Type
Description

id

long

Transaction record id.

title, subtitle

string

Display strings.

amount

string

Signed decimal string (e.g. "-15.50", "+1000.00").

type

string

Transaction type: P2P, FRX, CTU, CRD, CDP, CWD, CTF, CSW, ONR, UNKNOWN.

timestamp

long

Unix seconds.

currency

string

Transaction currency (e.g. USD, EUR).

direction

string

IN or OUT.

txHash, chainId

string

On-chain identifiers; chainId is CAIP-2.

inputToken, inputAmount, inputTokenAddress

string

Source asset (CTU).

outputAmount

string

FX output (FRX).

mcc

uint64

Merchant category code (CRD).

reference, fee, transferredAmount, notes

string

Channel-specific extras (CWD/CDP/CTU/ONR).

4. Request Example

5. Error Codes

Code
Type
Description
Solution

10000

DefError

Default error containing specific business error info.

Check request parameters or upstream service status.

10001

Auth Failure

Signature Verification Failed

Check headers, signature, and deadline validity.

3.1.7 Update Card Status

1. Description Modifies the status of the user's debit card. This is primarily used to "Freeze" (Block) the card to prevent unauthorized usage or "Unfreeze" (Unblock) it to resume normal operations.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v2/card-status

Auth Level

Full Auth

Requires wallet signature

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier (e.g., 5000)

sign

Wallet Signature

hash

Original request hash

deadline

Signature deadline

Request Parameters

Parameter
Type
Required
Description
Example

cardTokenId

string

Yes

The Card's Token (Note: This is the card's specific ID, not the user's URID). The value is 'cardToken', can be retrieved from the /cards interface.

"1001"

status

int

Yes

Target status code. 0: Inactive (Blocked/Frozen) 1: Active (Unblocked)

0

3. Response

4. Request Example

5. Error Codes

Code
Type
Description
Solution

10000

DefError

Default error containing specific business error info.

Card not found, invalid status code, or upstream service error.

10001

Auth Failure

Signature Verification Failed

Check signature and headers.

3.1.8 Permit (Token Approval)

1. Description Submits an EIP-2612 compatible permit signature. This allows the UR contracts to spend tokens from the user's wallet (When spending with the card, the UR contract will deduct the fiat balance from the user's UR account.) without the user needing to execute an on-chain approve transaction.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v1/token-permit

Auth Level

Full Auth

Requires API-level wallet signature

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier (e.g., 5000)

sign

Signature and Verify Signature

hash

Original request hash

deadline

API Signature deadline

Request Parameters

Parameter
Type
Required
Description
Example

address

string

Yes

The contract address of the token being approved (e.g., USDC, USDT).

"0x..."

amount

string

Yes

The amount to approve (decimal string).

"100"

permitAmount

string

Yes

The permit amount signed in the EIP-2612 permit (decimal string).

"100"

permitDeadline

int

Yes

The Unix timestamp (seconds) until which the permit is valid.

1735689600

permitV

int

Yes

EIP-2612 permit signature component v.

28

permitR

string

Yes

EIP-2612 permit signature component r (32 bytes hex).

"0x..."

permitS

string

Yes

EIP-2612 permit signature component s (32 bytes hex).

"0x..."

3. Response

Result Field Description

Field
Type
Description

txHash

string

The transaction hash of the permit execution (if the server relays it immediately) or status confirmation.

4. Request Example

You can find the token addresses at here.

5. Error Codes

Code
Type
Description
Solution

10000

System Error

Execution failed

Check if the deadline has expired or if the signature is invalid.

10001

Auth Failure

API Signature Verification Failed

Check headers and API-level authentication.

10009

Invalid Param

Malformed signature parameters

Ensure v, r, s are correctly formatted.

3.1.9 Get Supported Chain Config

1. Description Queries the chain configuration information supported by the UR application, including the list of tokens on each chain, user balances, card issuance eligibility status, and Token activity configurations.

Note: This interface supports queries in both logged-in and non-logged-in states.

  • Non-logged-in: Only queries supported chains and contract addresses.

  • Logged-in: Additionally returns the user's asset information.

Call Scenarios:

  • Getting supported chains and token lists when the App starts.

  • Refreshing balances when the user enters the asset page.

  • Querying token info on the target chain before top-up.

  • Querying supported chains and contract addresses before withdrawal .

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v3/config/chain-configs

Auth Level

Full Auth

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier: 5000

sign

Wallet Signature

hash

Original request hash

deadline

Signature deadline

3. Response

Success Response (HTTP 200):

Result Field Breakdown:

Main Response Structure:

Field Name
Type
Description

chains

array

List of supported chain configurations

canActivateCard

boolean

Whether the card can be activated

cardActivationMessage

string

Message prompt for card activation status

tokenActivities

array

List of Token activity configurations

**chains Array Element Structure (ChainInfo):

Field Name
Type
Description

chainIdentifier

string

Unique chain identifier (CAIP-2 format, e.g., eip155:1)

chainName

string

Human-readable name of the chain

chainLogoUrl

string

URL of the chain Logo

tokens

array

List of tokens supported on this chain

nativeToken

object

Native token information

depositContract

string

Deposit contract address

eip7702DelegationContract

string

EIP-7702 Delegation contract address

bufferPoolContract

string

Buffer Pool contract address (for Onramp)

**tokens Array Element Structure (TokenInfo):

Field Name
Type
Description

tokenIdentifier

string

Unique token identifier (contract address or special value)

symbol

string

Token symbol (USDC, ETH, etc.)

name

string

Full name of the token

logoUrl

string

URL of the token Logo

decimals

int

Token decimals

displayDecimals

int

Frontend display decimals

isFiat

boolean

Whether it is a fiat token

totalBalance

string

User balance (Decimal String)

totalBalanceUsd

string

USD value of the balance

isNative

boolean

Whether it is a native token

canDeposit

boolean

Whether deposit is supported

canWithdraw

boolean

Whether withdrawal is supported

aggregatorSupported

boolean

Whether DEX aggregator is supported

priority

int

Sorting priority

minTopUpAmount

string

Minimum Off-ramp amount for this token, in the token's own units (converted from a USD anchor at the live rate).

maxTopUpAmount

string

Maximum Off-ramp amount for this token, in the token's own units (converted from a USD anchor at the live rate).

minTopUpAmountUSD

string

USD anchor behind minTopUpAmount; identical across tokens.

maxTopUpAmountUSD

string

USD anchor behind maxTopUpAmount; identical across tokens.

minFxAmount

string

Minimum FX amount for this token, in the token's own units (converted from a USD anchor at the live rate).

maxFxAmount

string

Maximum FX amount for this token; reflects the user's remaining rolling 30-day allowance, so it changes over time.

minFxAmountUSD

string

USD anchor behind minFxAmount; identical across tokens.

maxFxAmountUSD

string

USD anchor behind maxFxAmount.

Amount limits: how to read them. The minTopUpAmount and maxTopUpAmount fields bound Off-ramp; "top-up" is the chain config's name for an Off-ramp deposit. The minFxAmount and maxFxAmount fields bound FX. UR derives each limit from a single USD anchor and converts it to the token's own units at the live exchange rate, so the value differs across tokens and moves with rates. Read these fields at request time; do not hardcode them. The ...USD fields carry the underlying USD anchor, which is the same for every token.

**tokenActivities Array Element Structure (TokenActivity):

Field Name
Type
Description

symbol

string

Associated token symbol

title

string

Activity title (may contain dynamic APY)

targetUrl

string

Link to jump to on click

targetType

string

Jump type (webview/native/external)

Response Field Details:

  • chains: List of supported chains.

  • Sorted by priority, usually the Mantle chain comes first.

  • Each chain contains configuration for tokens, contract addresses, etc.

  • balance field is not included for non-logged-in users .

  • canActivateCard: Card issuance eligibility.

  • Valid only in logged-in state.

  • Logic: Checks if any bank fiat balance on the Mantle chain is ≥ 1 USD.

  • true: User meets the conditions for card issuance.

  • false: Does not meet conditions .

  • cardActivationMessage: Card issuance prompt text.

  • Used in conjunction with canActivateCard.

  • Informs the user of the card issuance status or guides the operation .

  • tokenIdentifier: Token identifier.

  • ERC20 Token: Contract address.

  • Native Token: Usually 0x0000000000000000000000000000000000000000 or "NATIVE" .

  • CAIP-2 Format:

  • Chain identifiers use the CAIP-2 standard.

  • Format: <blockchainId>:<chainId>

  • Example: eip155:1 (Ethereum), eip155:5000 (Mantle) .

  • Decimal String:

  • Amount fields use string format.

  • Avoids JavaScript large integer precision issues.

  • Example: "1000.00", "0.000001" .

4. Request Example

Basic Query - Non-logged-in State:

Logged-in State - Get Balance and Card Status:

Full Request Example:

5. Error Codes

Error Code
Error Type
Description
Solution

10000

System Error

Database query failed, Nacos config retrieval failed

Retry later or contact technical support

10001

Auth Failure

Invalid tokenId format

Check if tokenId format is correct

10009

Invalid Param

address parameter format error

Ensure address is a valid hexadecimal address

Error Response Examples:

Common Error Troubleshooting:

i. Nacos Config Retrieval Failure (10000):

  • Token activities may not show.

  • The main flow (chain configuration) is unaffected.

  • Check Nacos service status .

ii. Balance Query Timeout (10000):

  • May be encountered by logged-in users.

  • Likely due to slow chain node response.

  • Balances for some chains may be missing .

iii. Address Format Error (10009):

  • Ensure the address starts with 0x.

  • Ensure it is a valid hexadecimal string.

  • Address length should be 42 characters (0x + 40 hex) .

Usage Instructions:

  • Cache Strategy:

  • Recommended cache time: 5-10 minutes.

  • Balance data needs frequent refreshing .

  • Version Compatibility:

  • Older versions of the App will automatically filter USDe.

  • Ensure App version ≥ 3.3.0 to access full features .

  • Chain List Sorting:

  • Sorted by the priority field.

  • Mantle chain usually ranks first .

  • Token Filtering:

  • App version < 3.3.0 will filter USDe.

  • Filtering logic can be controlled via User-Agent .

4. Offramp

This section introduces APIs and webhooks related to Offramp operations. Subsections are organized by chain family (e.g. EVM vs non-EVM); §4.1 covers EVM-compatible networks, and §4.2 covers Solana.

Amount limits. Read the minimum and maximum Off-ramp amount for each source token from the chain config fields minTopUpAmount and maxTopUpAmount; see Get Supported Chain Config. Read them at request time and do not hardcode them, because UR converts a USD anchor at the live rate for each token. The resulting USDC amount must be at least 5 USDC; UR rejects a smaller amount with error code 20003. Each Off-ramp also counts against the user's rolling 30-day fiat limit.

4.1 Offramp API for EVM

Note: The APIs and contract-oriented flows in §4.1 apply to EVM-compatible chains only—for example Ethereum mainnet (L1), Arbitrum One, Base, Mantle, and other supported networks that use CAIP-2 eip155:* chain IDs. Solana offramp is documented in §4.2.

4.1.1 Get Quote

1. Description Retrieves the best quote for a cross-chain cryptocurrency deposit. The system aggregates multiple DEXs (such as 1inch, Odos, etc.) to find the optimal exchange route, calculates network fees, cross-chain fees, and the final output amount, providing the user with complete deposit quote information.

Business Scenarios:

  • Cross-chain Deposit Process: Users holding tokens on other chains (e.g., Ethereum, Arbitrum) want to deposit into UR.

  • USDC Direct Deposit: Users holding USDC can deposit directly without exchange.

  • Non-USDC Token Deposit: Users holding other tokens (e.g., ETH, USDT) need to exchange them for USDC before depositing .

  • Fee Estimation: Users need to understand the complete fee structure and the final amount to be received before executing a deposit.

  • Quote Caching: To avoid repeated queries, the system caches quotes for 60 seconds to improve response speed.

DEX Aggregation Mechanism:

  • Multi-Source Quotes: Queries multiple DEX aggregators (1inch, Odos, etc.) simultaneously.

  • Optimal Selection: Selects the best route based on expected output amount, price impact, Gas fees, etc.

  • Redis Caching: Quotes with identical parameters are cached for 60 seconds.

  • Slippage Protection: Default slippage is 0.5% (50bps), customizable .

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v1/partner/quote/deposit

Auth Level

Basic Auth

No status restriction

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

Request Parameters (DepositQuoteReq)

Parameter
Type
Required
Description
Example

chainId

string

Yes

Source Chain ID (CAIP-2 format).

"eip155:1" (Ethereum), "eip155:42161" (Arbitrum)

userAddress

string

Yes

User wallet address (used to build the route).

"0x1234...5678"

fromToken

string

Yes

Source token address (Use 0x00...00 for native tokens).

"0xA0b8...B48" (USDC)

toToken

string

Yes

Target fiat token contract address. See token contract addresses.

"0xD598...aCC" (USD)

amount

string

Yes

Deposit amount (in smallest unit, e.g., Wei).

"1000000000000000000" (1 ETH)

Parameter Notes:

  • chainId: Follows CAIP-2 standard (eip155:<chainId>). Common values: eip155:1 (Ethereum), eip155:5000 (Mantle), eip155:42161 (Arbitrum One), eip155:10 (Optimism).

  • fromToken: Use the zero address 0x0000000000000000000000000000000000000000 for native tokens (e.g., ETH, MATIC).

  • amount: The input token amount, must be in the token's smallest unit. (e.g., 1 ETH = 10^18 Wei; 1 USDC = 10^6 units).

  • slippageBps: slippageBps is the maximum allowable deviation of the final output value from the estimated output during trade execution. This value determines the minOutputAmount. For example, 50 equals a 0.5% tolerance.

  • toToken: You can get all the fiat token addresses from here: token contract addresses

3. Response

Response Parameters (DepositQuoteResp)

Parameter
Type
Description
Example

quoteId

string

Unique quote identifier (Format: <source>_<timestamp>).

"1inch_1705...", "ur_1705..."

chainId

string

Source Chain ID.

"eip155:1"

best

BestQuote

Details of the best quote (see table below).

networkFee

string

Estimated network fee (denominated in Native Token); paid by the user from the source chain wallet.

"1250000000000000" (0.00125 ETH)

crossChainFee

string

Cross-chain fee (denominated in Native Token); paid by the user from the source chain wallet.

"500000000000000" (0.0005 ETH)

outputAmount

string

The estimated net amount of target fiat currency to be received, after deducting all applicable fees from the 'best quote'.

95.5 for 95.5 USD

inputAmount

string

Deposit amount (in smallest unit, e.g., Wei).

"5000000"

exchangeRate

string

Exchange rate (1 USDC = ? Target Fiat).

"1.0"

amountReceived

string

The actual USDC amount received on Arbitrum (in smallest unit, e.g., Wei). Only returned for Tempo chain offramp.

"4950000"

BestQuote Structure

Parameter
Type
Description
Example

aggregator

string

DEX aggregator name.

"1inch", "odos", "ur" (Direct)

to

string

Exchange contract address (Zero address for direct USDC deposit). If a user interacts with offramp contract directly, this value is required as the contract input parameter \_aggregator.

"0x1111..."

swapCalldata

string

Call data for the exchange ("0x" for direct USDC deposit). If a user interacts with offramp contract directly, this value is required as the contract input parameter \_swapCalldata.

"0x12aa..."

minUsdcAmount

string

Minimum USDC output amount (after slippage).

"990000000" (990 USDC)

expectedUsdcAmount

string

Expected USDC output amount.

"1000000000" (1000 USDC)

slippageBps

int32

Slippage basis points.

50 (0.5%)

deadline

int64

Quote expiration timestamp (Unix seconds).

1705123516

priceImpact

string

Price impact percentage.

"0.05" (0.05%)

4. Request Examples

Basic Example (ETH Deposit):

Arbitrum USDC Direct Deposit:

5. Error Codes

Code
Description
Reason

10001

Auth Failure

Token invalid or expired.

10002

Parse Error

Malformed request body.

10006

Status Not Supported

Account not active (Non-Live status).

10009

Invalid Param

Missing chainId/fromToken/amount, or amount <= 0.

10051

Invalid Chain ID

Unsupported chainId.

10052

No Available Quotes

All DEX queries failed.

10053

No Best Route

Could not determine best route from DEX quotes.

10054

Calculation Failed

Failed to calculate network or cross-chain fees.

11006

Insufficient Liquidity

Cross-chain liquidity is insufficient.

6. Common Error Troubleshooting

Error Message
Reason
Solution

"invalid params"

chainId/fromToken/amount is empty.

Check if all required parameters are complete.

"amounts must be greater than 0"

amount <= 0 or format error.

Ensure amount is a valid positive number string.

"invalid chain"

chainId not in supported list.

Use a valid CAIP-2 format Chain ID.

"no available quotes"

All DEX aggregator queries failed.

Check network connection or retry later; liquidity might be insufficient.

"no best route found"

Cannot select best route from quotes.

Retry with adjusted amount.

"calc fee amount: ..."

Fee calculation failed.

Check if Gas Price interface is available.

4.1.2 Initiate Offramp

In External Wallet Access Mode, users are expected to interact directly with the smart contract via the Partner Frontend by default.

Contract: depositTokenViaAggregator on the Off-ramp contract. Contract addresses per chain: see Deposit (Off-ramp).

Contract Parameters:

Parameter
Type
Required
Description
Example

_inputToken

address

Yes

Source token address (Use 0x00...00 for native tokens).

"eip155:1" (Ethereum), "eip155:42161" (Arbitrum)

_outputToken

address

Yes

Target fiat token identifier (Fiat type after deposit).

"0x1234...5678"

_amount

uint256

Yes

Deposit amount (in smallest unit, e.g., Wei).

For USDC: "10000000" as 10.000000

_aggregator

address

Yes

Exchange contract address get from the quote API

_swapCalldata

bytes

Yes

Get from the quote API response

"0x" for USDC direct deposit.

_minUsdcAmount

uint256

Yes

Get from the quote API response.

_feeAmountViaUsdc

unit256

Yes

Put "0" when user call the contract directly.

For Tempo chain, use depositWithFee on the Tempo Off-ramp contract. Contract addresses per chain: see Deposit (Off-ramp).

Contract Parameters:

Parameter
Type
Required
Description

inputToken

address

Yes

Source stablecoin address.

inputAmount

uint256

Yes

Deposit amount (in smallest unit, e.g., Wei).

outputToken

address

Yes

Target fiat token address.

minAmountReceived

uint256

Yes

Minimum amount to receive on Arbitrum. Calculate from the quote API: amountReceived adjusted by slippageBps.

refundAddress

address

Yes

Address to receive refund of excess cross-chain fee. Usually the user's wallet address.

maxFeeUsdcAmount

uint256

Yes

First-hop (Tempo → Arbitrum) cross-chain fee budget (denominated in USDC, in smallest unit). Calculate from the quote API: crossChainFee adjusted by slippageBps.

feeAmountViaUsdc

uint256

Yes

Put "0" when user calls the contract directly.

If you still require the ability for users to complete Offramp operations via an API, please contact the UR team.

4.2 Offramp API for Solana

Note: §4.2 applies to Solana only. Today, Solana deposit (offramp) supports USDC on Solana swapped into fiat balance on the UR side. Support for additional tokens via Jupiter (and similar aggregators) is planned; this page will be updated when that ships.

4.2.1 Get Quote

1. Description

Returns execution parameters and a fiat-credit quote for a Solana USDC deposit. The endpoint does not submit any on-chain transaction: it returns addresses, fee estimates, optional server-built unsigned Solana transactions, and rule flags the partner must respect when building or signing.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/v1/solana/deposit/quote

Relative to Partner OpenAPI base URL

Headers

Content-Type

Fixed: application/json

Request body parameters

Parameter
Type
Required
Description

urId

int64

Yes

User URID.

solanaAddress

string

Yes

User’s Solana address (Base58); must match the key that will sign the deposit transaction.

usdcAmount

string

Yes

Planned USDC input amount in smallest units (USDC uses 6 decimals), e.g. "10000000" for 10 USDC.

outputCurrency

string

Yes

Target fiat currency code (e.g. "USD").

minUsdcAmount

string

No

Client-side slippage floor in smallest units; must not exceed usdcAmount. If omitted or "0", the on-chain slippage check is skipped. See minUsdcAmount notes below.

network

string

No

Solana cluster: "mainnet" (or "mainnet-beta") for production, "devnet" for testing. Defaults to "devnet" if omitted — production callers must pass "mainnet" explicitly.

computeUnitPrice

uint64

No

Solana priority fee in micro-lamports per compute unit. If omitted, the server default is 1000. Raise under congestion if needed.

Parameter notes

  • usdcAmount: Minimum deposit is 5 USDC ("5000000"). Requests below this threshold are rejected with code 20003.

  • minUsdcAmount: The on-chain contract checks net_amount >= minUsdcAmount, where net_amount = usdcAmount - fee_amount. Because fee_amount is deducted before the check, passing a minUsdcAmount equal to usdcAmount will cause the transaction to revert with SlippageExceeded when fees are non-zero. Recommended: omit this field (or pass "0") for USDC-only deposits; only set it when integrating a swap path with meaningful slippage.

  • network: The server resolves program addresses, RPC endpoints, and LayerZero configuration based on this value. Using the wrong value (or omitting it in production) will return 50002 — solana chain config not found.

Example request body (mainnet)

Example request body (devnet)

3. Response

Successful responses use code: 0 and return details under data. Field names are stable; some fiat / fee fields may be omitted depending on environment.

Example response (mainnet)

Example response (devnet)

Response fields (data)

Field
Type
Description

network

string

Solana genesis hash (first 32 bytes, Base58). Mainnet: 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp; devnet: EtWTRABZaYq6iMfeYKouRu166VU2xqa1. Use this value to confirm the response matches the cluster you requested.

programId

string

Solana OApp program id (Base58).

oapp

string

Store PDA for the OApp (Base58).

endpointProgramId

string

LayerZero Endpoint program id (Base58).

dstEid

uint32

LayerZero destination endpoint id (Mantle side).

usdcMint

string

Solana USDC mint (Base58).

depositUsdcAccount

string

USDC token account that receives the deposit (Base58).

feeReceiver

string

Protocol fee receiver (Base58).

evmOutputToken

string

Mantle-side output token contract address (0x…).

nativeFeeLamports

string

Estimated LayerZero messaging fee in lamports (1 SOL = 10^9 lamports); paid by the user (the user is the Solana transaction fee payer).

nativeFeeLamportsWithBuffer

string

Recommended lamport budget with ~20% buffer; prefer passing this as the transaction’s native fee / value where applicable.

rules

object

Enforced constraints on the Solana side (see Rules object below).

transaction

string

Optional Base64 VersionedTransaction (v0), unsigned. If empty or missing, build the transaction manually from the other fields.

lastValidBlockHeight

uint64

Upper bound block height for the blockhash inside transaction. If the chain passes this height before confirmation, request a new quote.

outputAmount

string

Estimated net fiat amount (may be omitted).

outputAmountBeforeFee

string

Fiat amount before fees (may be omitted).

exchangeRate

string

USDC → target fiat rate (may be omitted).

processingFee

string

Processing fee component (may be omitted).

networkFee

string

EVM-side network fee; often "0" in Solana quote context (may be omitted).

totalFee

string

Total fees (may be omitted).

Rules object (data.rules)

Field
Type
Typical meaning

onlyUsdc

bool

Deposit path must use USDC only.

swapDataMustBeEmpty

bool

No inline swap payload unless officially supported.

jupiterRemainingAccountsLenMustBeZero

bool

Jupiter remaining accounts must be empty (future aggregator hooks).

userMustHaveUsdcAta

bool

User must already have a USDC ATA; create it first if missing.

feePayerMustBeUser

bool

Fee payer on the Solana transaction must be the user.

Response signature (optional)

The server may return x-api-signature and x-api-publicKey headers so the client can verify the response body against UR’s signer (same pattern as other Partner OpenAPI responses).

4. Error codes

Code
Description

10001

Partner authentication failed (invalid signature, wrong key, or expired deadline).

20003

Invalid parameters: bad urId, malformed address, unsupported outputCurrency, or user not under this partner.

50002

Internal configuration error (e.g. missing Solana program config).

50003

On-chain RPC failure or quote engine failure.

5. Common troubleshooting

Symptom
Likely cause
What to do

50002 — solana chain config not found

network field is missing or wrong; omitting it defaults to "devnet" which does not exist in production config.

Pass "network": "mainnet" explicitly for production calls.

20003 — amount must be at least 5 USDC

usdcAmount is below the minimum 5 USDC (5000000).

Increase the amount to at least "5000000".

20003 — invalid minUsdcAmount

minUsdcAmount is non-numeric or exceeds usdcAmount.

Omit the field or pass a value ≤ usdcAmount.

SlippageExceeded (on-chain 0x1773)

minUsdcAmount set to usdcAmount while on-chain fee is > 0; contract checks net_amount (post-fee) >= minUsdcAmount.

Omit minUsdcAmount or set it to "0" for USDC-only deposits.

20003 after fixing params

User record not provisioned for this partner / chain

Ensure the user exists for this partner (provisioning flows are documented elsewhere).

Transaction never lands

Blockhash expired

Compare current block height to lastValidBlockHeight; call quote again.

Simulation failure (ProgramFailedToComplete)

Compute unit limit too low or missing USDC ATA.

The server pre-built transaction already includes a SetComputeUnitLimit instruction; if building manually, set at least 400,000 CU. Also ensure the user has a USDC ATA.

Simulation failure (other)

Wrong signer or account mismatch

Obey rules; ensure solanaAddress matches the signing key.

4.2.2 Execute Offramp Transaction

After a successful quote, the partner (or user wallet) must sign and submit the Solana transaction. UR recommends using the pre-built data.transaction when it is present.

Recommended path: pre-built transaction

When data.transaction is non-empty:

  1. Base64-decode to bytes and deserialize with @solana/web3.js VersionedTransaction.deserialize.

  2. Before signing, run structural validation against the expected deposit layout (see §4.2.3), including validateDepositViaAggregatorTx(tx, quote.programId) when using the reference sketch.

  3. Recommended before signing: refresh recentBlockhash via connection.getLatestBlockhash and rebuild the VersionedTransaction (same compiled instructions). Quote responses may sit for seconds before the user signs; a fresh blockhash improves landing rate and pairs with a current lastValidBlockHeight for confirmation.

  4. Sign with the user’s Solana key (must match solanaAddress in the quote request).

  5. simulateTransaction with sigVerify: true before broadcast.

  6. sendTransaction to the correct RPC for the quoted network.

  7. Poll confirmation using blockhash / lastValidBlockHeight that match the signed transaction (from step 3 if you refreshed; otherwise from the quote). If the blockhash expires before confirmation, obtain a new quote and retry.

If data.transaction is empty, assemble the deposit instruction manually using programId, accounts, rules, and fees—contact UR for bytecode-level docs if you are not using the pre-built path.

Example (Node.js)

Dependencies: @solana/web3.js (with TransactionMessage.decompile / compileToV0Message, as in recent releases) and a Partner OpenAPI client that implements request signing as in §4.2.1.

Pass quoteRequestBody with the same shape as §4.2.1 (including urId, solanaAddress, usdcAmount, outputCurrency, and optional network / computeUnitPrice). Use a partner-signed callOpenApi implementation consistent with your environment. Implement validateDepositViaAggregatorTx as in §4.2.3 (or import an equivalent module).

Malicious browser extensions, compromised front-end bundles, or man-in-the-middle proxies could swap the Base64 transaction returned by /v1/solana/deposit/quote for a different VersionedTransaction before the user signs. To reduce that risk, always validate the instruction layout and program IDs after Base64 decode and before any signature.

What a legitimate UR pre-built deposit transaction looks like

For the current USDC-only path, UR expects a VersionedTransaction (v0) whose compiled instructions are exactly three:

Index
Expected program
Role

0

ComputeBudget (ComputeBudgetProgram.programId)

Typically SetComputeUnitLimit

1

ComputeBudget

Typically SetComputeUnitPrice (priority fee)

2

UR deposit program (data.programId from the same quote response)

deposit_via_aggregator (Anchor discriminator + Borsh payload)

Reject transactions with fewer than three instructions, more than three instructions, or any program id on the third instruction that does not match the programId returned alongside transaction in that quote.

Address lookup tables (ALT)

The reference programIdForIx helper below resolves each instruction’s program id from message.staticAccountKeys only. That matches typical UR pre-built data.transaction payloads from this endpoint, where each of the three instructions’ programIdIndex values point into staticAccountKeys (no extra lookup-table resolution needed).

If you deserialize a transaction where programIdIndex >= staticAccountKeys.length, the program id is supplied through one or more address lookup tables. In that case you must resolve the full account key list (for example via VersionedTransaction + loaded lookup tables, or APIs that hydrate MessageV0 account keys) and compute the program id for each instruction from that resolved list—then compare instruction 2 to quote.programId. Until you extend the sketch that way, the validator may throw or reject a transaction that is valid on-chain.

Program id by environment (reference)

Always treat the programId field in the quote response as the source of truth. Published examples:

Network

programId (Base58)

USDC Mint

Solana mainnet-beta

DgiyAgiEJDt4hXw56mpKDd7mcYRYUaxrKg3ConyeupYX

EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v

Solana devnet

FgWV99azAfJLSnSQprTKVyq7zCyLJEK4QiJ3ri3GPrAo

4ArjZDc2B1jLXtqpKCkPfXrkkfFoqsi19bxcDoTJmpiL

Instruction data (third instruction)

The third instruction’s data should decode as deposit_via_aggregator: 8-byte Anchor discriminator (first 8 bytes of sha256("global:deposit_via_aggregator")), followed by Borsh fields such as inputAmount, minUsdcAmount, evmRecipient, evmOutputToken, nativeFee, swapData length and payload, and jupiterRemainingAccountsLen. For the current USDC-only ruleset, data.rules from the quote may require empty swap/Jupiter tails—align validation with those flags when you decode.

Reference validation sketch (Node.js)

The following pattern matches production checks when program ids are indexed via staticAccountKeys: assert VersionedTransaction, resolve each instruction’s program id from message.staticAccountKeys, require instructions 0–1 to be Compute Budget and instruction 2 to equal expectedProgramIdFromQuote, then decode the third instruction’s data and ensure the discriminator matches deposit_via_aggregator. See Address lookup tables (ALT) above if you need full lookup resolution.

Call validateDepositViaAggregatorTx(tx, quote.programId) immediately after VersionedTransaction.deserialize(...), then proceed to tx.sign([...]). You can extend the decoder to compare inputAmount / minUsdcAmount / nativeFee against the user’s intended quote parameters for defense in depth.

5. Onramp

This section documents Fiat-to-Crypto Onramp in External Wallet Access Mode.

5.1 Onramp API

5.1.1 Get Onramp Limit

1. Description Returns user-specific onramp eligibility signals and amount caps. This endpoint does not return a single isSupport boolean. Integrators must evaluate:

  • regionLocked

  • usdcDepegged

  • livenessLocked

  • maxAmounts

  • minAmounts

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v1/onramp-limit

Auth Level

Full Auth

Live account required

Headers

Content-Type

Fixed: application/json

tokenId

User‘s URID

network

Network Identifier

sign/hash/deadline

Full Auth signature

3. Response

4. Result Fields

Field Name
Type
Description

livenessLocked

bool

Whether liveness is currently locked for this user.

livenessLockMins

int64

Remaining lock duration in minutes (0 if unlocked).

maxAmounts

map[string]string

Max allowed onramp amount by fiat currency (no token decimals).

minAmounts

map[string]string

Min allowed onramp amount by fiat currency (no token decimals).

usdcDepegged

bool

Whether USDC depeg protection is active.

regionLocked

bool

Whether onramp is region-restricted for this user.

Read maxAmounts and minAmounts per fiat currency; do not hardcode them. UR derives both from a single USD anchor (about 5 USD minimum; the maximum depends on the user's liveness state) and converts each to fiat at the live exchange rate, so the values differ across currencies and move with rates.

5. Request Example

6. Error Codes

Code
Description
Reason

10001

Auth Failure

Invalid authentication or signature.

10002

Parse Error

Invalid request format.

10000

Service Error

Internal failure when calculating limits.

5.1.2 Get Onramp Quote

1. Description Returns quote for both:

  • scene=onramp: Fiat token -> destination token

  • scene=swap_retry: retry swap using destination-chain USDC

The response includes needLiveness. Quote results are cached server-side and later validated by submit/retry endpoints.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v1/quote/onramp

Auth Level

Full Auth

Live account required

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier

sign/hash/deadline

Full Auth signature

Request Parameters

  • You can get all the fiat token addresses from here: token contract addresses

  • The amount in the request body is the smallest unit, that means 10000 USD here equals 100 USD

3. Response

  • The *AmountOut values in the response body is in the smallest unit. For example: 12345000 USDC equals 12.345 USDC.

  • Key Fields

Field Name
Type
Description

quoteId

string

Quote identifier used by submit/retry endpoints.

best.to

string

The value of dstAggregator in the Onramp request API

best.swapCalldata

string

The value of dstSwapCalldata in the Onramp request API

outputAmount

string

The estmated human readable output amount

exchangeRate

string

Includes the swap price impact and spreads

displayRate

string

When the displayUnit==1, same as exchangeRate, but if the input currency is JPY, the displayUnit will be 100, and displayRate will be 100JPY -> 1 XXX token

processingFee

string

Charged for normal users, pro users can ignore

networkFee

string

Includes the estimated gas fee and crosschain fee, deducted from the user's input fiat.

needLiveness

bool

If true, user must pass liveness before onramp submit.

4. Request Example

5. Error Codes

Code
Description
Reason

10001

Auth Failure

Invalid authentication or signature.

10002

Parse Error

Malformed request body.

10009

Invalid Param

Unsupported scene/token/chain, empty fields, or invalid amount.

10040

Quote Try Again

Quote unavailable/expired; request a new quote.

10000

Service Error

Internal quote computation failure.

5.1.3 Get Liveness Token (Onramp Compliance)

1. Description Creates a Sumsub liveness access token for onramp flow. Call this only when quote returns needLiveness=true.

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v2/get-liveness-token

Auth Level

Full Auth

Live account required

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier

sign/hash/deadline

Full Auth signature

3. Response

4. Request Example

5. Error Codes

Code
Description
Reason

10001

Auth Failure

Invalid authentication or signature.

10000

Service Error

Liveness locked or upstream token generation failed.

5.1.4 Check Liveness Result

1. Description Polls latest liveness status for current user in onramp scenario.

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v2/check-liveness-result

Auth Level

Full Auth

Live account required

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier

sign/hash/deadline

Full Auth signature

3. Response

4. Result Fields

Field Name
Type
Description

liveness_result

string

Liveness status (pass, pending, rejected, etc.).

checked_at

int64

Unix seconds when latest liveness check was processed.

expired_at

int64

Unix seconds when current pass status expires (if applicable).

liveness_fail_reason

string

Failure reason if rejected.

liveness_locked

bool

Lock status due to repeated failures.

liveness_unlock_at

int64

Unix seconds when lock ends (if locked).

5. Error Codes

Code
Description
Reason

10001

Auth Failure

Invalid authentication or signature.

10041

Liveness Check Not Found

No liveness record yet.

10000

Service Error

Internal liveness query failure.

5.1.5 Initiate Onramp With Permit

1. Description Submits onramp transaction with permit signature. Requires valid cached quote and (if required) passed liveness.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v1/onramp-with-permit

Auth Level

Full Auth

Live account required

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier

sign/hash/deadline

Full Auth signature

Request Parameters

3. Response

4. Important Notes

  • Backend validates request fields against quote cache (quoteId binding).

  • If quote expired or mismatched, submit is rejected.

  • If eligibility says liveness is still required, submit is rejected.

5. Error Codes

Code
Description
Reason

10001

Auth Failure

Invalid authentication or signature.

10002

Parse Error

Malformed request body.

10009

Invalid Param

Invalid amount/address/permit fields, or quote mismatch.

10040

Quote Try Again

Quote expired; request a new quote.

10000

Service Error

Eligibility check/permit validation/onchain submission failed.

5.1.6 Check Pending Retry

1. Description Returns one pending onramp retry candidate (if any). This endpoint is used for post-onramp retry handling when destination swap previously failed.

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v1/onramp/pending-retry

Auth Level

Full Auth

Live account required

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier

sign/hash/deadline

Full Auth signature

3. Response

If no retry is available:

If retry is available:

4. Error Codes

Code
Description
Reason

10001

Auth Failure

Invalid authentication or signature.

10000

Service Error

Internal retry query failure.

5.1.7 Retry Swap With Permit

1. Description Executes destination-chain swap retry for a failed onramp record.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v1/onramp-swap-with-permit

Auth Level

Full Auth

Live account required

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier

sign/hash/deadline

Full Auth signature

Request Parameters

3. Response

4. Important Notes

  • Retry call requires a valid retry quote from scene=swap_retry.

  • Request fields must match quote cache and original retry record.

  • Do not call this endpoint directly without pending-retry + quote preparation.

5. Error Codes

Code
Description
Reason

10001

Auth Failure

Invalid authentication or signature.

10002

Parse Error

Malformed request body.

10009

Invalid Param

Invalid amount/address/permit fields, quote mismatch, or state mismatch.

10040

Quote Try Again

Retry quote expired; request a new retry quote.

10000

Service Error

Internal retry validation or onchain submit failure.

5.1.8 Cancel Retry

1. Description Cancels a pending retry (can_retry) for an onramp transaction.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v1/onramp/retry/cancel

Auth Level

Full Auth

Live account required

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier

sign/hash/deadline

Full Auth signature

Request Parameters

3. Response

4. Important Notes

  • This is not the default path when no pending record exists.

  • Use only when a retry-eligible transaction exists and user explicitly abandons retry.

5. Error Codes

Code
Description
Reason

10001

Auth Failure

Invalid authentication or signature.

10002

Parse Error

Malformed request body.

10009

Invalid Param

Missing or invalid originalTxHash.

10000

Service Error

Internal query/update failure during cancellation.

5.2 End-to-End Flow

  1. Call GET /api/v1/onramp-limit.

  2. Call POST /api/v1/quote/onramp with scene=onramp.

  3. If quote returns needLiveness=true:

  • Call GET /api/v2/get-liveness-token.

  • Run Sumsub SDK in client.

    Example for Sumsub SDK calling:

  • After the user completes the above Sumsub process, step 2 (POST /api/v1/quote/onramp) can be called again. When needLiveness = false, the user may proceed with the transaction.

  1. When liveness result is pass (or not required), call POST /api/v1/onramp-with-permit.

  1. Periodically call GET /api/v1/onramp/pending-retry.

  2. If response contains pending object:

  • Call POST /api/v1/quote/onramp with scene=swap_retry.

  • Call POST /api/v1/onramp-swap-with-permit.

  1. If user decides not to retry, call POST /api/v1/onramp/retry/cancel.

5.3 Error Codes & Troubleshooting

Common Codes in Onramp

Code
Description
Typical Meaning

10000

DefError

Generic backend/internal failure.

10001

AuthenticationFailure

Invalid token/signature/header auth data.

10002

ParseRequestFailed

Invalid request shape or JSON parse failure.

10009

ParamInvalid

Invalid parameter values or business-state mismatch.

10040

QuoteTryAgain

Quote expired/unavailable; request a fresh quote.

10041

LivenessCheckNotFound

No liveness record available yet.

Troubleshooting Matrix

Error Message / Signal
Reason
Solution

needLiveness=true in quote

User amount/eligibility requires liveness verification

Complete liveness flow before submit.

Face verification required

Submit attempted before passing required liveness

Poll liveness result; submit only after liveness_result=pass.

Quote expired. Please request a new quote.

Quote cache missing/expired/mismatch

Re-request quote and submit with matching parameters.

Empty result from pending-retry

No retry-eligible record currently (can_retry not found)

Continue periodic polling; do not call retry endpoint directly.

Retry submit rejected

Missing retry quote or quote/original record mismatch

Re-run retry sequence: pending-retry -> quote(scene=swap_retry) -> retry submit.

6. Bank Transfer

This section covers payout transfer flows for existing external-wallet users. For recipient/contact listing, use the existing Get User Profile endpoint and its contacts field.

6.1 Create/Select Recipient

6.1.1 Get Supported Banks

1. Description Returns supported banks and country metadata (including whether IBAN metadata is available).

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v1/banks

Auth Level

No Auth

3. Response

Sample is truncated for documentation; production response contains additional countries/banks in the same format.

6.1.2 Get Bank by IBAN

1. Description Resolves bank details from an IBAN.

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v1/banks/iban/{ibanNo}

Auth Level

No Auth

3. Response

6.1.3 Get Supported Recipient Countries and Cities

1. Description Returns supported recipient country/city combinations for transfer setup.

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v1/country-cities

Auth Level

No Auth

3. Response

Sample is truncated for documentation; production response contains more countries/cities in the same format.

6.1.4 Get Payment Purpose List

1. Description Retrieves supported payment purpose options used for compliance validation before transfer.

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v1/payment-purposes

Auth Level

No Auth

3. Response

6.1.5 Verify Reference

1. Description Verifies user-entered payment reference text and returns purposeId and ref.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v1/verify-reference

Auth Level

Full Auth

Requires wallet signature

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier

sign

Wallet Signature

hash

Original request hash

deadline

Signature deadline

Request Parameters

3. Response

6.1.6 Verify Contact (Bank Payment Request)

1. Description Validates final recipient and bank payload (bankPaymentRequest) and returns contactId, purposeId, and refId.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v1/verify-contact

Auth Level

Full Auth

Requires wallet signature

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier

sign

Wallet Signature

hash

Original request hash

deadline

Signature deadline

Request Parameters

3. Response

6.2 Permit & Transfer

6.2.1 Get Fees

1. Description Returns configured payout fees and minimum payout amounts by currency.

2. Request

Item
Value
Note

HTTP Method

GET

URI

/api/v1/banks/payout/fees

Auth Level

No Auth

Request Parameters

No request body.

3. Response

6.2.2 Create Payout Permit Request

1. Description Creates payout transfer request with user wallet signature (permit-style authorization) and submits on-chain payout.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v1/payout-with-permit

Auth Level

Full Auth

Requires wallet signature

Request Parameters

3. Response

4. Notes

  • Recipient name/address/reference fields should use Latin characters.

  • Minimum input for USD payouts is typically 50 USD.

  • Gas/network fee is deducted from the user's fiat transfer amount.

6. Representative Error Conditions

Type
Description

Signature Error

User signature verification failed.

Monthly Limit Exceeded

Transfer exceeds monthly quota.

Insufficient Balance

Available fiat balance is insufficient.

Minimum Amount Error

Transfer amount below minimum allowed input.

7. FX

This section describes the recommended FX execution flow in External Wallet Access Mode:

  1. Call POST /api/v1/quote/fx to get the quoted outputAmount and exchangeRate.

  2. Use the quote result to build amountOutMinimum.

  3. Call POST /api/v1/fx-exchange-with-permit to execute the on-chain exchange.

Amount limits. Read the minimum and maximum FX amount for each token from the chain config fields minFxAmount and maxFxAmount; see Get Supported Chain Config. Read them at request time and do not hardcode them. UR converts the minimum from a USD anchor at the live rate. The maximum reflects the user's remaining rolling 30-day allowance, so it changes over time.

7.1 FX API

7.1.1 Get Output Amount and Exchange Rate

1. Description Returns quoted FX output amount (minimal unit) and exchange rate for a token pair.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v1/quote/fx

Auth Level

Basic Auth

Requires tokenId header

Headers

Content-Type

Fixed: application/json

tokenId

User's URID

network

Network Identifier (5000 Mainnet, 5003 Testnet)

Request Parameters

3. Response

4. Field Notes

  • inputAmount / outputAmount: minimal unit strings (do not treat as float).

  • exchangeRate: 1 inputToken = x outputToken, fixed 2 decimals, truncated down.

  • Current quote mode is exact_in (input is fixed).

5. Request Example

7.1.2 Exchange with Permit

1. Description Executes FX on-chain using EIP-2612 style permit signature.

2. Request

Item
Value
Note

HTTP Method

POST

URI

/api/v1/fx-exchange-with-permit

Auth Level

Full Auth

Requires signed headers + permit fields

Headers

tokenId

User's URID

network

Network Identifier

sign

Wallet signature header

hash

Request hash header

deadline

Header signature deadline

Request Parameters

3. Response

4. Parameter Notes

  • inputAmount: exact-in amount (minimal unit).

  • amountOutMinimum: minimum acceptable output (minimal unit), usually derived from quote outputAmount.

  • permitValue: must be >= inputAmount.

  • permitDeadline: must be in the future.

  • permitR / permitS: 32-byte hex strings (0x + 64 hex chars).

  1. Call POST /api/v1/quote/fx with inputAmount, inputToken, outputToken.

  2. Read result.outputAmount and result.exchangeRate.

  3. Decide amountOutMinimum policy:

    • conservative: apply a safety factor on quote output;

    • strict: use quote outputAmount directly.

  4. Build permit signature for inputToken.

  5. Call POST /api/v1/fx-exchange-with-permit.

  6. Track final transaction status via txHash.

Code
Type
Description

10002

Parse Error

Missing/malformed parameters or headers

10009

Invalid Param

Invalid token address, amount format, or token pair

10040

Quote Try Again

Quote failed due to pricing/rpc conditions; retry quote

10000

System Error

Permit verification or on-chain submission failed

8. OPEN API

This section details the UR-OPEN-API, designed for third-party integrations (B-side). For complete API documentation including authentication, endpoints, and data structures, please refer to the Open API Reference.

8.1 MINT

See Mint URID in the Open API Reference.

8.2 Get User Profile

See Fetch UR Account Information in the Open API Reference.

8.3 Get User Balance

See Fetch UR Account Balance in open API Reference.

8.4 Transaction Query

See Fetch Transaction Details and Fetch Transaction History in the Open API Reference.

8.5 Webhook Notifications

Webhook definitions are centralized in Webhooks. For off-ramp related events, see transaction and allowance.

Last updated