API reference: Managed Custody Mode
Core banking API reference for partners integrating via Managed Custody Mode.
This document is the Core Banking OpenAPI reference for Partners integrating with UR in Managed Custody Mode. Section 3 covers onboarding for Partners whose users complete KYC in the Partner's Sumsub flow and share that verification with UR through Sumsub reuse. Fund-moving APIs still require the user's UR account to be
Liveand the mapped Partner user to exist.For the conceptual definition of Managed Custody Mode and how it compares to External Wallet Access Mode, see Integration Guide.
1. Mode Context
1.1 Where This API Sits
Managed Custody Mode is one of UR's two Account Modes. In this mode:
The user's UR account (URID + tokenized fiat balances) lives inside a UR-managed embedded wallet.
The Partner backend accesses that account entirely through REST APIs, signed with the Partner's signer key.
Routine banking actions (FX, Pay-in, Payout, On-ramp, Off-ramp, Card) are submitted by the Partner's backend; UR validates, runs compliance / risk / limit checks, and executes the on-chain settlement using UR's wallet infrastructure.
The user is not prompted to sign on-chain transactions for routine banking actions.
The Partner owns the entire UX surface; UR is the regulated banking infrastructure underneath.
1.2 Operation Layer Map
Every Core Banking endpoint maps to one of UR's six core operations. This table is the canonical anchor for the rest of this document.
Card
User → merchant via Mastercard
§11 (Card-Mode-specific — see API Reference: Card Mode — Crypto Backed)
Real-time authorization, async settlement
Read-only endpoints (Profile §5, Balance §6, Transactions §12) sit beside these operations.
2. API Foundation
2.1 Base URLs
Production
https://openapi.ur.app
Preview
https://openapi-preview.ur.app
Testnet
https://uropenapi-qa.ur-inc.xyz
Confirm the exact base URL set with UR before production rollout.
2.2 Authentication — Partner Auth (EIP-191)
All authenticated Partner → UR requests use Partner Auth with EIP-191 signatures.
Every authenticated request must include:
X-Api-Signature
Yes
0x-prefixed 65-byte hex signature over the canonical request payload, produced with the Partner signer's private key.
X-Api-Deadline
Yes
Unix seconds. UR rejects the request if now > deadline. Recommended validity window ≤ 5 min.
X-Api-PublicKey
Yes
The Partner signer address (0x-prefixed). Must be registered with UR.
Canonical payload:
GETrequests sign the raw query string exactly as sent, without the leading?.Non-
GETrequests sign the raw request body exactly as sent.Append the user identity suffix to that payload before signing:
urId:{X-Ur-Id}externalUserId:{X-External-User-Id}. If a header is not sent, use an empty value in its slot.
For example, a POST body of {"amount":"100"} with X-Ur-Id: 7123456789 and no X-External-User-Id signs:
For the EIP-191 recovery algorithm, see Signature and Verification.
2.3 User Identity Headers
Every user-scoped Partner → UR endpoint must identify the user with at least one of the following headers.
X-Ur-Id
The user's URID (numeric token ID of the URID NFT).
X-External-User-Id
The Partner's own user ID, mapped to a URID during onboarding.
Rules:
Send at least one of
X-Ur-IdorX-External-User-Id. Sending neither is invalid.Sending both is allowed. When both are present, UR resolves the user by
X-Ur-Idfirst.User identity must not be duplicated in query parameters or request bodies for user-scoped APIs.
Example:
or:
2.4 Header Block References
To avoid repeating long header tables, endpoint sections refer to these named blocks.
Partner-Scoped Partner Auth Headers — Partner Auth headers (§2.2) only, no user identity. Used for partner-level endpoints not tied to a single user.
Public Metadata Headers — No auth required. Used for fully public reference endpoints (banks, payment purposes, etc.). UR reserves the right to change this access policy.
2.5 Standard Response Envelope
Core Banking APIs use the standard UR OpenAPI response envelope:
code = 0→ success; non-zero → business error (see endpoint-specific tables and the global error code reference).message→ human-readable explanation, may be empty on success.data→ endpoint-specific payload.
2.6 Idempotency
Endpoints that move funds (Off-ramp submission, FX, Payout, On-ramp, Onramp retry) accept a Partner-supplied idempotency key:
The field name is
reqId.Keep
reqIdstable across retries of the same logical operation. Replays with the samereqIdreturn the original outcome instead of re-executing.Webhook delivery is at-least-once — use
data.txHashor the transactionidas the idempotency key on the Partner side.
2.7 Preconditions for Fund-Moving APIs
Before calling Off-ramp, On-ramp, FX, Payout, or Card APIs, the Partner must ensure:
The UR account status is Live.
The mapped Partner user and UR account exist and are not frozen.
Any integration-specific approval required by UR has been enabled for your production setup.
3. Onboarding
Use this section when your platform verifies the user through your own Sumsub tenant. During onboarding, your platform shares the completed Sumsub applicant with UR through Sumsub's share-token reuse mechanism. UR reruns the required checks against UR's Sumsub level, creates a URID, provisions the UR-managed wallet, renders and signs Form A, and activates the user's UR Account.
Two onboarding paths are supported:
Sumsub reuse (this page). Your platform completes KYC in your own Sumsub tenant and shares the approved applicant with UR through Sumsub reuse. Use this when you already operate a Sumsub tenant.
Sumsub SDK on user device. Your backend requests a UR-issued Sumsub access token and the Sumsub SDK on the user device runs KYC against UR's Sumsub tenant. See API reference: Managed Custody SDK KYC. Use this when you do not run a Sumsub tenant.
Both paths produce the same end state and use the same post-onboarding banking APIs documented in this page.
3.1 Prerequisites
Before you start onboarding users, make sure the following setup is complete:
Your Partner Auth signing key is registered with UR.
Your platform and UR are configured as Donor / Recipient Partners in Sumsub.
Your backend can generate a Sumsub share token scoped to UR's Sumsub
clientIdafter the applicant is approved.Your backend can submit the share token through your dedicated integration channel.
Your backend can persist
externalUserId,sessionId,urId, andevmAddressfor each user.Your backend can receive onboarding webhooks from UR, especially
fma.kyc.retry_required.
Store the returned identifiers before you show the user that onboarding has started. Your externalUserId is your stable user ID. UR maps that value to the returned urId.
3.2 Identity headers during onboarding
Onboarding uses the same Partner Auth rules as the rest of this page. The identity header changes after UR creates the user's UR Account.
Pre-account
POST /api/fma/v1/create-account
X-External-User-Id
Do not send X-Ur-Id before UR returns the user's urId.
Post-account
/api/fma/v1/kyc/* and /api/fma/v1/account-status
X-Ur-Id
Use the urId returned by /create-account. Sending X-External-User-Id as well is allowed.
For GET /api/fma/v1/kyc/form-a-info and GET /api/fma/v1/account-status, sign the raw query string exactly as sent. For POST endpoints, sign the raw request body exactly as sent. Append the same identity suffix described in §2.2.
3.3 Onboarding flow
The onboarding flow starts after the user has completed KYC in your Sumsub workflow and your backend has shared the approved applicant with UR through Sumsub reuse. UR validates the reused KYC snapshot, records the required attestation on UR's Sumsub level, and activates the UR Account asynchronously.
3.4 Create account
Create or reuse the user's UR Account and onboarding session.
Method
POST
Path
/api/fma/v1/create-account
Headers
Partner Auth headers + X-External-User-Id
Request body:
Request fields:
applicantId
Yes
The completed Sumsub applicant ID in your tenant. UR uses this value to match the applicant shared through Sumsub reuse.
email
Yes
The user's email address.
Response example:
Rules:
Repeated calls with the same
X-External-User-Idreturn the existing onboarding session withidempotentReplay=true.Persist
sessionId,urId, andevmAddressbefore continuing.Use
X-Ur-Idon subsequent onboarding calls.
3.5 Check KYC completeness
Validate the user's reused Sumsub applicant and check whether the session can proceed to Form A.
Method
POST
Path
/api/fma/v1/kyc/check
Headers
User-Scoped Partner Auth Headers
Request body:
Complete response:
Incomplete response:
Poll this endpoint every 30 seconds to 2 minutes while the user is completing KYC or while UR is waiting for the Sumsub reuse result. Stop polling after /kyc/submit succeeds, or when the session reaches a terminal state.
Error handling:
20004
The KYC snapshot is incomplete.
Ask the user to finish the missing Sumsub steps, then poll again.
40001
Sumsub is temporarily unavailable.
Back off and retry.
40002
UR cannot match the applicantId to a reusable Sumsub applicant.
Check the applicantId and share-token setup for the user.
3.6 Get Form A
Fetch the exact Form A text that the user must review.
Method
GET
Path
/api/fma/v1/kyc/form-a-info?sessionId={sessionId}
Headers
User-Scoped Partner Auth Headers
Request body: none.
Response example:
Rules:
Display
data.textto the user exactly as returned.Pass
data.textHashunchanged to/kyc/sign-form.textHashis the0x-prefixed keccak256 hash of the UTF-8 bytes ofdata.text.If this endpoint returns
20007, the KYC snapshot is not ready. Return to/kyc/check.
3.7 Sign Form A
Ask UR to sign the rendered Form A text with the user's UR-managed custodial wallet.
Method
POST
Path
/api/fma/v1/kyc/sign-form
Headers
User-Scoped Partner Auth Headers
Request body:
Response example:
Rules:
The request does not include a user signature. UR produces the Form A signature using the user's UR-managed wallet.
textHashmust match the latest Form A text rendered by UR.If user data changes before
/kyc/submit, call/kyc/form-a-infoagain and re-sign the latesttextHash.
3.8 Submit onboarding
Submit the completed onboarding session for asynchronous account activation.
Method
POST
Path
/api/fma/v1/kyc/submit
Headers
User-Scoped Partner Auth Headers
Request body:
Response example:
The registrationId can be empty in the synchronous response. UR fills downstream activation details asynchronously. Use fma.account.result or /api/fma/v1/account-status to confirm the final state.
Preconditions:
/kyc/checkhas returnedcomplete=true.Form A has been signed through
/kyc/sign-form.The session is in
Registerstate.
3.9 Get account status
Use account status as a polling fallback after /kyc/submit, or as an explicit confirmation before enabling fund-moving features.
Method
GET
Path
/api/fma/v1/account-status
Headers
User-Scoped Partner Auth Headers
Response example:
Poll this endpoint at a 1-minute cadence after /kyc/submit if you do not receive fma.account.result. Stop polling when data.statusStr is Live, Blocked, or Closed.
3.10 Onboarding states
Use the following state values for your local onboarding cache:
PartnerDataIngestion
UR created the onboarding session and is waiting for a complete KYC snapshot.
Call /kyc/check after the Sumsub applicant is complete.
IdentityVerification
UR is still validating identity evidence.
Continue polling /kyc/check, or ask the user to complete missing KYC steps.
SignFormA
The KYC snapshot is ready for Form A.
Call /kyc/form-a-info, display the text, then call /kyc/sign-form.
Register
Form A is signed and the session is ready to submit.
Call /kyc/submit.
Submitting
UR is activating the account with the downstream banking partner.
Wait for fma.account.result or poll /api/fma/v1/account-status.
Completed
The UR Account is activated.
Enable fund-moving features only after account-status returns Live.
Failed
UR rejected or expired the onboarding session.
Show the failure state and wait for UR guidance or a retry webhook.
3.11 Onboarding webhooks
UR sends onboarding webhooks to the webhook URL registered for your integration. Verify every webhook with the same EIP-191 recovery rules in §13.2.
Activation or rejection:
When data.status is activated, confirm Live with /api/fma/v1/account-status before enabling fund-moving features. When data.status is rejected, the payload includes rejectCode and rejectReason.
Retry required:
When you receive fma.kyc.retry_required, store retrySessionId and run the onboarding flow again from /kyc/check against the retry session. Do not call /create-account for a retry session.
4. Core banking integration principles
The following rules apply across all fund-moving endpoints in this reference.
User balances are queried with
GET /api/fma/v1/balance(§6.1).Off-ramp converts crypto (held on a supported source chain) into the user's tokenized fiat balance. For the current set of supported source chains, source tokens, and target fiat currencies, see Supported Chains & Tokens.
On-ramp converts the user's tokenized fiat balance into crypto on a supported destination chain. New On-ramp submissions must be blocked while a pending retry exists. For the current set of supported destination chains and tokens, see cryptos with
aggregatorSupportedvalue in the response of Supported Chains & Tokens.Card authorization behavior depends on the Partner's Card Mode. See API Reference: Card Mode — Crypto Backed for the Crypto Backed integration surface; Card Mode: Fiat Only has no Partner-side authorization surface.
All async settlement results are delivered via the transaction webhook (§13). The webhook is the authoritative source of truth — API responses to fund-moving calls return only a
txHash(the operation has been submitted on-chain, not yet settled).
5. Profile
5.1 Get BR Profile
Fetch the user's banking profile, including IBAN, fiat limits, contacts, deposit bank details, and card eligibility.
Method
GET
Path
/api/fma/v1/br
Headers
User-Scoped Partner Auth Headers
Request body: none. Query parameters: none.
Response example:
Notes:
limitsare denominated in CHF and use a rolling 30-day window.FX, card spending, on-ramp, and payout share the same fiat limit bucket.
A single transaction must not exceed
limits.available.
6. Balance
6.1 Get User Balance
Fetch the user's fiat and crypto balances held inside the user's UR account.
Method
GET
Path
/api/fma/v1/balance
Headers
User-Scoped Partner Auth Headers
Response example:
fiatItemsenumerates the user's tokenized fiat balances on Mantle (EUR24, CHF24, USD24, etc.).cryptoItemsenumerates any crypto held inside the user's UR-managed wallet, if Partner has enabled crypto-holding for that user.
7. Off-ramp
Off-ramp converts crypto into fiat in the user's UR account.
Currently supported:
Source chains and tokens: see Supported Chains & Tokens
Target fiat currencies: USD, EUR, CHF, SGD, JPY, HKD
Flow
The UR API step is quote retrieval. After the Partner receives the quote, the user (via the Partner Frontend) signs and submits the Off-ramp contract call from whichever wallet holds the source crypto. See §7.2.
7.1 Get Off-ramp Quote
Method
POST
Path
/api/fma/v1/quote/deposit
Headers
User-Scoped Partner Auth Headers
Request body:
chainId&fromToken— see Supported Chains & TokenstoCurrency— target fiat currency symbol.amount— human-readable decimal string; UR converts it to token smallest units using the source token decimals.
Response example:
Contract execution notes:
Pass
best.to,best.swapCalldata, andbest.minUsdcAmountto the UR Off-ramp contract exactly as returned.The signing Crypto Wallet (UR-managed or external; see §7.2) must have approved the Off-ramp contract to spend
fromTokenfor at leastamount.The transaction must be submitted before
best.deadline; otherwise it can revert.networkFeeandcrossChainFeeare denominated in the source chain's native token and paid by the user from the source chain wallet (in addition toamount).Final settlement is reported asynchronously through the transaction webhook with
data.type = "CRYPTO_DEPOSIT".
7.2 Initiate Off-ramp
In Managed Custody Mode, the Fiat Wallet is always UR-managed, but the Crypto Wallet could be the same as the UR-managed account or an external wallet, depending on the Partner's choice. The Off-ramp contract is agnostic to the source — it uses the _targetAccount parameter to know which UR Account receives the resulting fiat.
Contract: depositTokenViaAggregatorToAccount on the Off-ramp contract. Contract addresses per chain: see Deposit (Off-ramp).
Contract Parameters:
_inputToken
address
Yes
Source token address (Use 0x00...00 for native tokens).
"0xA0b8...B48" (USDC)
_outputToken
address
Yes
Target fiat token address (Fiat type after deposit).
"0x1234...5678"
_amount
uint256
Yes
Deposit amount (in smallest unit, e.g., Wei).
For USDC: "10000000" = 10.000000
_aggregator
address
Yes
Exchange contract address — use best.to from §7.1.
_swapCalldata
bytes
Yes
Use best.swapCalldata from §7.1.
"0x" for USDC direct deposit.
_minUsdcAmount
uint256
Yes
Use best.minUsdcAmount from §7.1.
_feeAmountViaUsdc
uint256
Yes
Put "0" when user calls the contract directly.
_targetAccount
address
Yes
Use data.targetAccount from §7.1. This is the user's UR Account address that receives the resulting fiat.
If you require Partner-side API submission for Off-ramp instead of on-chain user signing, please contact the UR team.
8. FX
FX converts one tokenized fiat balance into another tokenized fiat balance, both held inside the user's UR account.
8.1 FX Quote
Method
POST
Path
/api/fma/v1/quote/fx
Headers
User-Scoped Partner Auth Headers
Request body:
Response example:
8.2 Execute FX
Method
POST
Path
/api/fma/v1/fx-exchange
Headers
User-Scoped Partner Auth Headers
Request body:
amountOutMinimum is optional. If omitted, UR applies a default 0.5% slippage buffer based on the submitted amount.
Response example:
Final result is reported through the transaction webhook with data.type = "FRX". See §12.1 for the full set of status values.
9. Bank Payout
Bank Payout sends tokenized fiat from the user's UR account to an external bank account via SEPA / SWIFT.
Flow
9.1 Get Payout Fees
Method
GET
Path
/api/v1/banks/payout/fees
Headers
Public Metadata Headers
Public metadata, not scoped to a single user. Returns the standard envelope:
9.2 Choose Recipient
The Partner can use either a recent contact returned by GET /api/fma/v1/br, or create / verify a new contact.
Recent contact path:
Read
data.contacts[currency]from the BR Profile response (§5.1).Use
contact.idascontactId.If the user provides a new reference, call
POST /api/fma/v1/verify-reference(§9.3) to get a freshrefId+purposeId.
New contact path:
Identify the recipient bank by IBAN (
GET /api/v1/banks/iban/{iban}) or by selecting from the non-IBAN bank list (GET /api/v1/banks).Collect required creditor name, address, country, city, payment purpose, and reference.
Call
POST /api/fma/v1/verify-contact(§9.4).
Public metadata APIs (/api/v1/banks, /api/v1/banks/iban/{iban}, /api/v1/country-cities, /api/v1/payment-purposes) do not require user identity headers unless UR changes their access policy.
9.3 Verify Reference
Method
POST
Path
/api/fma/v1/verify-reference
Headers
User-Scoped Partner Auth Headers
Request body:
Response example:
9.4 Verify Contact
Method
POST
Path
/api/fma/v1/verify-contact
Headers
User-Scoped Partner Auth Headers
Request body:
Response example:
creditorInfo.name, creditorInfo.street, creditorInfo.city, and creditorInfo.country must use Latin characters.
9.5 Submit Payout
Method
POST
Path
/api/fma/v1/submit-payout
Headers
User-Scoped Partner Auth Headers
Request body:
Response example:
Constraints:
metadataname, address, and reference values must use Latin characters.purposeIdandrefIdmust be provided together, or both omitted.Minimum amount is currency-specific and comes from
minimalPayoutAmount(§9.1).Network fees and payout fees are deducted from
amount; they are not charged separately.Payout is subject to the user's rolling 30-day CHF-denominated fiat limits.
Final result is reported through the transaction webhook with
data.type = "FIAT_WITHDRAW".
10. On-ramp
On-ramp converts the user's tokenized fiat balance into crypto on a target chain.
Currently supported:
Destination chains and tokens: see cryptos with
aggregatorSupportedvalue in the response of Supported Chains & Tokens.Source fiat currencies: USD, EUR, CHF, SGD, JPY, HKD
Flow
10.1 On-ramp Login Initialization
When the user enters the On-ramp flow, the Partner should run these checks in order:
GET /api/fma/v1/onramp-limitGET /api/fma/v1/onramp/pending-retry— only if the limit response allows the flow.
If a pending retry exists, the Partner must force the user to Retry or Cancel before starting a new On-ramp.
10.2 Get On-ramp Limit
Method
GET
Path
/api/fma/v1/onramp-limit
Headers
User-Scoped Partner Auth Headers
Response example:
Block the flow if regionLocked, usdcDepegged, or livenessLocked is true, or if the requested amount exceeds maxAmounts[currency].
10.3 Check Pending Retry
Method
GET
Path
/api/fma/v1/onramp/pending-retry
Headers
User-Scoped Partner Auth Headers
Pending retry represents an On-ramp whose bridge succeeded but whose swap leg failed; the user must resolve it before starting a new On-ramp.
No pending item:
When there is no pending retry, data.originalTxHash is empty.
Pending item:
10.4 Get On-ramp Quote
Method
POST
Path
/api/fma/v1/quote/onramp
Headers
User-Scoped Partner Auth Headers
Request body for the main On-ramp flow:
Notes:
sceneisonrampfor the main flow andswap_retryfor retry (§10.8).srcChainIdis the chain where the user's tokenized fiat is held (UR's home chain).fromCurrencyis required forscene = "onramp".fromTokenis used only forscene = "swap_retry".dstChainIdandtoTokenmust match a crypto type withaggregatorSupportedvalue in the response of Supported Chains & Tokens.networkFeereturned in the quote response is the destination-chain gas + cross-chain fee, deducted from the user's input fiat.If the response has
needLiveness = true, the Partner must complete liveness before submitting On-ramp.
10.5 Liveness Token
Method
GET
Path
/api/fma/v1/onramp-liveness-token
Headers
User-Scoped Partner Auth Headers
Only call this endpoint when a quote returns needLiveness = true.
Response example:
10.6 Liveness Result
Method
GET
Path
/api/fma/v1/onramp-liveness-result
Headers
User-Scoped Partner Auth Headers
Response example:
After liveness_result = "pass", the Partner should request a new quote and submit using the new quoteId.
10.7 Submit On-ramp
Method
POST
Path
/api/fma/v1/onramp
Headers
User-Scoped Partner Auth Headers
Request body:
Response example:
Submit constraints:
amountInis a human-readable decimal string and must match the amount used for the cached quote.quoteIdmust match UR's cached quote (and not be expired).A quote requiring liveness cannot be submitted until liveness passes.
New On-ramp must be blocked while a pending retry exists (§10.3).
withdrawAddressis optional and is only supported for cross-chain On-ramp (chainId != dstChainId).If
withdrawAddressis omitted, UR sends the destination-chain crypto to the user's UR EVM address.Do not send
withdrawAddressfor same-chain On-ramp (chainId == dstChainId); the request will be rejected.Final result is reported through the transaction webhook.
10.8 Retry On-ramp Swap
On-ramp is a two-leg flow (bridge + swap). When the bridge succeeds but the swap fails, the user's funds are stuck as the bridge intermediate token on the destination chain. Retry redoes the swap leg only — so the payload drops fiat/source-chain inputs and instead carries originalTxHash, the post-bridge intermediate-token amount, and a fresh swap quote.
Method
POST
Path
/api/fma/v1/onramp-swap
Headers
User-Scoped Partner Auth Headers
Only call this endpoint when GET /api/fma/v1/onramp/pending-retry returns a pending item.
Retry flow:
Read pending retry from
GET /api/fma/v1/onramp/pending-retry.Request a fresh retry quote:
scene = "swap_retry"srcChainId = pendingRetry.chainIddstChainId = pendingRetry.chainIdfromToken = pendingRetry.fromTokentoToken = pendingRetry.toTokenamount = pendingRetry.amount(human-readable)
Submit
/api/fma/v1/onramp-swap:usdcAmount = pendingRetry.amountRaw(USDC minimal unit)tokenOut = pendingRetry.toTokenminAmountOut = quote.best.minAmountOutaggregator = quote.best.to(notquote.best.aggregator)swapCalldata = quote.best.swapCalldata
Request body:
10.9 Cancel On-ramp Retry
Method
POST
Path
/api/fma/v1/onramp/retry/cancel
Headers
User-Scoped Partner Auth Headers
Request body:
A successful response clears the pending retry record and allows the Partner to re-enable the normal On-ramp entry point.
11. Card
The user's debit card is issued and processed by UR through Mastercard. This section covers only the card-management endpoints common to all Card Modes: card creation, card info retrieval, default-currency selection, and post-settlement history.
Card authorization, prefund, and card-related webhooks are Card-Mode-specific. Card Mode: Fiat Only has no Partner-side authorization surface — UR handles authorization on-chain against the user's tokenized fiat balance. Card Mode: Crypto Backed has its own integration surface (synchronous authorization callback, Prefund Account, Prefund Balance Alert webhook) documented in API Reference: Card Mode — Crypto Backed.
11.1 Create Card
Create a virtual card for an eligible Live user.
Method
POST
Path
/api/fma/v1/open-card
Headers
User-Scoped Partner Auth Headers
Request body: {}
Preconditions:
GET /api/fma/v1/brreturnsisCardEligible = true.The user has no existing card if UR only allows one card per user.
The user balance satisfies
cardActivation.amountandcardActivation.currency.
Response example:
11.2 Get Card Info
Fetch card metadata and a short-lived cardToken for secure card display.
Method
GET
Path
/api/fma/v1/card
Headers
User-Scoped Partner Auth Headers
Response example:
Security constraints:
UR does not return real PAN, CVV, or expiry through this API.
maskedvalues are display placeholders only.The Partner backend must not store
cardToken.The Partner backend should only pass
cardTokento the frontend.The Partner frontend must pass
cardTokeninto the secure card display webview provided by UR. Real PAN, CVV, and expiry are rendered only inside that webview.
11.3 Set Default Card Currency
Set the user's default card transaction currency.
Method
POST
Path
/api/fma/v1/card-currency
Headers
User-Scoped Partner Auth Headers
Request body:
Response example:
Notes:
The target card is resolved server-side from the
urIdin the User-Scoped Partner Auth Headers; the Partner does not pass acardTokenId.The next
GET /api/fma/v1/cardresponse should show the updatedcurrency.This setting affects UR's default refund currency display and debit preference.
Per-transaction overrides at swipe time are governed by the Card Mode — see API Reference: Card Mode — Crypto Backed.
11.4 Card Authorization
Card authorization behavior is Card-Mode-specific and is not covered in this document. See API Reference: Card Mode — Crypto Backed for the Crypto Backed integration surface. Card Mode: Fiat Only has no Partner-side authorization surface.
11.5 Card Settlement Notes
Card settlement result records are exposed through transaction history (§12) with data.type = "CRD". Additional card adjustment event contracts (chargebacks, fee adjustments) must be agreed separately with UR.
12. Transactions
Use transaction history for reconciliation. The same endpoint also supports exact lookup by transaction hash or transaction ID.
12.1 Fetch Transaction History
Method
POST
Path
/api/fma/v1/transactions
Headers
User-Scoped Partner Auth Headers
Simple first-page request:
Filtered request:
Response example:
Pagination is driven by the response flags and cursors. Only send cursor fields returned by the API, and only when the corresponding flag is true.
To fetch the next page, use nextCursor when hasNextPage is true:
To fetch the previous page, use prevCursor when hasPrevPage is true:
If hasPrevPage is false, do not use prevCursor; a zero cursor means there is no previous page.
Request fields:
pageSize
integer
Page size. Defaults to 50; maximum is 100.
type
string
Single transaction type filter. Do not send together with txTypes.
txTypes
string[]
Multiple transaction type filter. Do not send together with type.
currencies
string[]
Currency filter. Values are normalized to lowercase by UR.
direction
string
Direction filter: IN, OUT, or ALL.
status
string
Transaction status filter.
chainId
string
Chain ID filter, for example eip155:5000.
tokenSymbol
string
Token symbol filter, for example USDC.
minAmount
string
Minimum amount filter.
maxAmount
string
Maximum amount filter.
fromTimestamp
integer
Start timestamp filter.
toTimestamp
integer
End timestamp filter.
cursorTimestamp
integer
Next-page cursor timestamp from data.nextCursor.timestamp.
cursorId
integer
Next-page cursor ID from data.nextCursor.id.
prevCursorTimestamp
integer
Previous-page cursor timestamp from data.prevCursor.timestamp.
prevCursorId
integer
Previous-page cursor ID from data.prevCursor.id.
id
integer
Exact lookup by UR internal transaction ID. Do not send together with txHash.
txHash
string
Exact lookup by transaction hash. Do not send together with id.
Partner-relevant transaction types:
type
Meaning
CRYPTO_DEPOSIT
Crypto deposit / tokenized fiat top-up.
INTERNAL_TOKEN_TRANSFER
Internal token transfer between UR accounts.
UNKNOWN
Unknown or uncategorized transaction type.
FX_EXCHANGE
FX exchange.
MARQETA_AUTHORIZE
Card authorization / card payment.
FIAT_WITHDRAW
Fiat withdrawal / bank payout.
FIAT_DEPOSIT
Fiat deposit / bank pay-in.
ONRAMP
On-ramp.
Transaction status values:
status
Description
UNKNOWN
Unknown; default value. Should not appear in normal flows.
INIT
Transaction created internally but not yet broadcast to the blockchain node.
PENDING
Transaction is in the mempool (transaction pool), awaiting confirmation.
CONFIRMED
Transaction has been confirmed and settled on-chain.
FAILED
Transaction execution failed on-chain.
PENDING_DROP
Transaction is scheduled to be dropped, for example replaced or cancelled.
DROPPED
Transaction was removed from the mempool without being confirmed.
REJECTED
Transaction was rejected by UR's validation or compliance checks before or during execution.
12.2 Fetch Transaction Details
Use this endpoint to fetch a single transaction. Send exactly one lookup key: txHash for an on-chain transaction hash, or id for UR's internal transaction ID.
Method
POST
Path
/api/fma/v1/transactions
Headers
User-Scoped Partner Auth Headers
Lookup by transaction hash:
Lookup by UR internal transaction ID:
Response:
The response uses the same
data.items[]transaction structure as §12.1.Send either
idortxHash, never both.If no transaction matches the lookup key,
data.items[]is empty.
13. Webhooks
Webhooks are the asynchronous delivery channel for transaction settlement updates. The Partner should subscribe to the transaction event for Off-ramp, FX, On-ramp, Fiat Deposit, and Payout settlement.
Card-Mode-specific webhooks (post-swipe card transaction,
prefund.balance.alert) are documented in API Reference: Card Mode — Crypto Backed.
13.1 Webhook Envelope
13.2 Webhook Signature Verification
UR signs webhook requests with EIP-191.
Partner verification steps:
Read the exact raw request body string (do not re-serialize).
Recover the signer address using the body and
X-Api-Signature.Accept the event only if the signer address matches the UR public key provided out of band.
See Signature and Verification for the canonical recovery algorithm.
13.3 Retry and Idempotency
The Partner should return
HTTP 200within 10 seconds.UR retries non-200 or timed-out webhook deliveries up to 3 times, with a 5-minute interval.
Use
data.txHashor the transactiondata.idas the idempotency key on the Partner side.
13.4 Transaction Event
The transaction event uses the same transaction data structure as /api/fma/v1/transactions (§12.1). Route by data.type — see the type table in §12.1 for the canonical set.
14. Implementation Checklist
Before going live:
Store both
externalUserId(Partner side) andurId(UR side) after onboarding.For user-scoped APIs, send at least one of
X-External-User-IdorX-Ur-Id(sending both is allowed; UR resolves byX-Ur-Idfirst).Sign
GETrequests with the raw query string, and sign non-GETrequests with the raw body, then appendurId:{X-Ur-Id}externalUserId:{X-External-User-Id}.Keep
reqIdstable across retries forPOST /api/fma/v1/fx-exchange,POST /api/fma/v1/submit-payout,POST /api/fma/v1/onramp, andPOST /api/fma/v1/onramp-swap.Treat webhook delivery as at-least-once and implement idempotency keyed on
data.txHashordata.id.Reconcile transaction history through
POST /api/fma/v1/transactions; usetxHashoridon that same endpoint for exact lookup.Verify every webhook with EIP-191 recovery against UR's public key (§13.2).
If the Partner is enabling Card Mode: Crypto Backed, complete the additional checklist in API Reference: Card Mode — Crypto Backed.
15. Reference Docs
Integration Guide — Account Mode, Card Mode, KYC Mode decisions.
API Reference: Card Mode — Crypto Backed — the Partner-side integration surface for Card Mode: Crypto Backed (authorization callback, Prefund Account, card-related webhooks).
API Reference: External Wallet Access Mode — the other Account Mode.
Last updated