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

Crypto Backed Card

Prefund operations, card authorization callback, and card webhooks for Crypto Backed mode.

This document is the Partner-facing API reference for Card Mode: Crypto Backed. It covers the three integration surfaces a Partner must implement on top of their chosen Account Mode: Prefund Account operations, the Card Authorization callback (UR → Partner, synchronous), and the Card Mode webhooks (post-swipe and Prefund balance alerts).

For the conceptual definition of Card Mode and how it relates to Account Mode, see Integration Guide. For the Account Mode API surfaces this mode plugs into, see API Reference: Managed Custody Mode or API Reference: External Wallet Access Mode.


1. Mode context

1.1 What Card Mode: Crypto Backed is

Card Mode answers a single question: when the user taps the card, which balance is debited?

  • Card Mode: Fiat Only: the card draws exclusively from the user's UR fiat balance. UR runs the authorization on-chain; the Partner is not in the authorization path.

  • Card Mode: Crypto Backed (this document): the card can settle directly against the user's crypto holdings via a Partner-funded Prefund Account, with no per-swipe off-ramp required. UR synchronously consults the Partner at authorization time; the Partner asynchronously debits the user's crypto after a successful swipe.

Card Mode is orthogonal to Account Mode; a Partner can pair Crypto Backed with either External Wallet Access Mode or Managed Custody Mode.

1.2 The two phases

Crypto Backed runs in two phases that operate on different timescales:

Phase
Initiator
Cadence
What happens

1. Prefund

Partner

Scheduled (recurring, or on alert)

Partner calls the UR off-ramp contract with USDC, targeting its own Prefund Account. The Prefund Account is credited in the Partner's settlement currency.

2. Card spend

User (tap)

Real-time

Mastercard routes the auth to UR → UR calls the Partner webhook → Partner returns a decision → UR settles against the Prefund Account (APPROVE) or the user's UR fiat balance (PASS) → after Mastercard finalizes, UR sends a post-swipe webhook to the Partner → on an APPROVE, the Partner debits the user's crypto.

The Prefund Account exists to absorb real-time card authorizations: Partners cannot bridge user crypto fast enough to meet UR's 1 s total authorization window, so UR is pre-funded and the Partner reconciles asynchronously.

1.3 What this document covers vs. doesn't

This document covers Partner-facing surfaces that exist only in Card Mode: Crypto Backed:

This document does NOT cover endpoints that are common to both Card Modes (Create Card, Get Card Info, Set Default Currency, Card history). Those live in the Account Mode API reference under the Card section:

1.4 Partner prerequisites

Before integrating Card Mode: Crypto Backed, the Partner must have:

  • An Account Mode chosen and operational (External Wallet Access or Managed Custody).

  • KYB (Know Your Business) completed with UR. UR requires KYB before it provisions your Prefund Account.

  • The ability to make an initial USDC off-ramp into the Prefund Account to seed card spending capacity.

  • The ability to schedule recurring off-ramp calls that top up the Prefund Account on a supported chain.

  • The ability to respond to the Card Authorization callback within 500 ms with valid Partner Auth signatures.

  • The ability to reliably debit user crypto after the swipe is approved, typically via a smart contract wallet under the Partner's programmatic control, or centralized custody, so the user cannot move the crypto between approval and debit. UR does not enforce this on the Partner's behalf.

  • Operational tolerance for working-float management; if the Prefund Account drains below the minimum balance, authorizations begin to decline.


2. API foundation

This document inherits the API foundation defined in the Account Mode reference: base URLs, Partner Auth (EIP-191) headers, response envelope, idempotency rules. See:

Two header-block shorthands are used below:

  • Partner-Scoped Partner Auth Headers: X-Api-Signature + X-Api-Deadline + X-Api-PublicKey, no user identity. Used for Prefund Account endpoints (§3).

  • UR-Signed Inbound: for requests where UR calls the Partner (§4 callback and §5 webhooks), UR signs the body with EIP-191 using UR's signer key. The Partner must verify the signature against UR's public key before acting on the payload.


3. Prefund Account

Scope: Partner-scoped (not user-scoped). One Prefund Account per Partner, regardless of how many users the Partner has onboarded. A single Prefund Account can hold a balance in more than one settlement currency.

3.1 What the Prefund Account is

The Prefund Account is a Partner-level operational funding account used to settle card swipes that the Partner approves with decision: APPROVE. The Partner funds it; UR debits it during card settlement; the Partner asynchronously debits the user's crypto to replenish its own books.

It is not:

  • A user balance; users cannot see it, cannot deposit to it, and cannot withdraw from it.

  • A real-time authorization gate the Partner queries per swipe. Use it for operational monitoring only; UR performs Prefund availability checks inside the Card Authorization flow (§4).

3.2 Funding the Prefund Account

You fund the Prefund Account yourself, by calling the UR off-ramp contract with your Prefund Account as the off-ramp target account. UR does not run an operator-mediated deposit step, and there is no separate deposit address to send crypto to.

Currently supported:

  • Off-ramp USDC on supported chains: call the off-ramp contract with USDC on any UR Supported Chain. USDC is the only deposit currency today.

  • Settlement currency: the currency your Prefund Account is held in, on Mantle, as a tokenized fiat balance. It defaults to USD. To use a different settlement currency, agree it with UR before onboarding; the settlement currency you pick affects your off-ramp pricing.

  • Minimum balance: agreed with UR during onboarding, per settlement currency. UR emits prefund.balance.alert (§5.5) when a currency's balance reaches or falls below its threshold.

Operational constraints:

  • Off-ramp to your own Prefund Account, never to a user account. Confirm your Prefund Account details with UR before your first production top-up, and use them as the off-ramp target account.

  • Do not assume an off-ramp is instantly reflected. The off-ramp settles asynchronously; monitor the Prefund Balance API (§3.3) and the prefund.balance.alert webhook (§5.5) rather than assuming the credit has landed.

  • Maintain a buffer above the minimum balance. Each prefund.balance.alert indicates the Partner is now exposed to authorization decline risk on the next swipe. Plan top-up SLA accordingly.

3.3 Get Prefund balance

Item
Value

Method

GET

Path

/api/fma/v1/prefund-balance

Headers

Partner-Scoped Partner Auth Headers

This endpoint is partner-scoped, not user-scoped. It returns the current state of the Partner's Prefund Account.

Request body: none. Query parameters: none.

Response example:

The response is a flat, single-currency object describing the Prefund Account's settlement currency (defaults to USD):

Response fields:

Field
Description

partnerId

Partner identifier registered with UR.

account

On-chain address of the Prefund Account (Mantle).

currency

The settlement currency, agreed with UR (defaults to USD, see §3.2).

balance

Current balance, decimal string.

minBalance

Minimum balance threshold. prefund.balance.alert fires when the balance reaches or falls below it.

level

Balance level relative to minBalance. This endpoint emits "normal" (balance > minBalance) or "warning" (balance ≤ minBalance) only.

allowance

The card-spend contract allowance for this account, as a human-readable amount.

updatedAt

Unix seconds, last balance update.

This endpoint returns a single currency and does not include a settleMode field. Record your configured settlement mode from onboarding; it is not read back from this response.

Usage recommendations:

  • Polling cadence: operational dashboard cadence, e.g. no more frequently than once per minute unless UR advises otherwise.

  • Authoritative source: treat this endpoint as the source of truth for balance and minBalance. Webhook payloads are eventually consistent.

  • Reactive pattern: use prefund.balance.alert (§5.5) as a passive trigger; call this endpoint to confirm current state before initiating a top-up.

  • Not for authorization decisions: do not call this endpoint from inside the Card Authorization callback (§4). UR already performs Prefund availability checks before approving. Adding a Partner-side check increases your 500 ms callback latency for no benefit.


4. Card authorization callback (UR → Partner)

Scope: Required only for Card Mode: Crypto Backed. Card Mode: Fiat Only Partners are not in the authorization path at all.

When the user taps the card, UR synchronously calls a Partner-hosted authorization endpoint. The Partner returns an approval decision and the currency to settle in; UR then performs final balance, limit, compliance, and Prefund checks before responding to Mastercard.

4.1 Settlement modes

Partners configure one of two settlement modes during onboarding. The mode determines what UR sends in the authorization request and what the Partner is expected to return.

Mode

settleMode

Description

Fixed

fixed (default)

UR pre-computes the exact amount it will debit from the Prefund Account, in the Partner's configured settlement currency, including FX spread and interchange. UR sends that amount in the settlement field of the authorization request. The Partner approves or declines against that pre-calculated amount, and does not choose the debit currency.

Partner Controlled

partner_controlled

The Partner chooses which Prefund settlement currency to debit on each swipe. UR sends the raw Mastercard transaction and settlement details, and the Partner returns the chosen currency in paidCurrency. Because UR does not know the currency in advance, it cannot pre-compute the debit amount; the Partner sizes it.

Fixed mode is designed for Partners who hold a single-currency Prefund Account and want UR to handle all FX conversion. The Partner does not need to perform any currency conversion; the settlement.amount in the request is the exact amount that will be debited from the Prefund Account.

4.2 Endpoint contract

The Partner hosts an endpoint at a URL registered with UR during onboarding (e.g. https://api.partner.example/ur/card-authorizations). UR calls it on every card authorization for users whose accounts are configured with Card Mode: Crypto Backed.

Item
Value

Method

POST

Path

Partner-hosted (registered with UR during onboarding)

Direction

UR → Partner

Auth

Mutual EIP-191: UR signs the request body; Partner signs the response body. Both parties verify the other's signature against pinned addresses.

Latency budget

≤ 500 ms Partner response time. The Partner's 500 ms sits inside UR's 1 s total authorization window; UR uses the remaining ~500 ms for internal checks.

Failure mode

Timeout / 5xx / signature-verification failure / invalid response → UR treats as DECLINE for this swipe.

The Partner's authorization endpoint should be low-latency, idempotent, auditable, and fail-safe. Treat the 500 ms budget as a hard ceiling; design for p99 well under it.

4.3 Flow

4.4 Request signing (UR → Partner)

UR signs every authorization request body with EIP-191 using UR's server private key. The signature and signer address are sent in HTTP headers:

Header
Description

X-Api-Signature

EIP-191 signature over the raw JSON request body (0x-prefixed hex, 65 bytes).

X-Api-PublicKey

UR's signer Ethereum address. The Partner must verify this matches the address pinned during onboarding.

X-Request-Id

Matches data.requestId in the body. Convenience header for logging.

Verification: recover the signer address from EIP191(body) using X-Api-Signature, then assert it equals the pinned UR public key. Reject if it doesn't match.

4.5 Request body (UR → Partner)

Field reference:

Field
Type
Description

event

string

Always "card_authorization".

timestamp

number

Unix seconds when the request was built.

data.version

string

Protocol version. Currently "1".

data.requestId

string

UR-generated idempotency key. The Partner must echo this back in the response and respond identically to retries with the same requestId.

data.expiresAt

number

Unix milliseconds. The Partner should reject requests where expiresAt < now.

data.action

string

"AUTHORIZE" for initial authorization, "INCREMENT" for an incremental auth on the same transaction.

data.partnerId

string

Partner identifier.

data.userId

string

User's UR ID.

data.authorizationToken

string

Card network authorization token.

data.transaction.currency

string

Merchant's transaction currency (ISO 4217 alpha code, e.g. "SGD").

data.transaction.amount

string

Transaction amount in the transaction currency (integer string in the token's smallest unit).

data.settlement.currency

string

Settlement currency symbol (e.g. "USD", "EUR"). In fixed mode, this is always the Partner's configured settleCurrency. In partner_controlled mode, this is the Mastercard network settlement currency.

data.settlement.amount

string

Settlement amount. Its meaning depends on your settleMode; read it accordingly. In fixed mode, this is the pre-computed Prefund debit amount, including FX spread and interchange. It is the exact amount UR debits from your Prefund Account if you approve, so you can check it against your balance directly. In partner_controlled mode, this is the Mastercard network settlement amount. It is not your Prefund debit; UR applies FX and interchange at execution, so convert it yourself before you size the debit.

data.merchant.*

object

Merchant details from the card network.

4.6 Response body (Partner → UR)

The Partner must sign the response body with EIP-191 and include signature headers:

Header
Description

X-Api-Signature

EIP-191 signature over body + " " + deadline (the response body bytes, a space, and the deadline string).

X-Api-Deadline

Unix seconds expiry for the response signature (e.g. 60 s from now).

X-Api-PublicKey

Partner's signer Ethereum address.

Approval:

Decline:

Pass (fall back to user's own balance):

Response field reference:

Field
Required
Description

requestId

Yes

Must match data.requestId from the request. UR rejects mismatches.

decisionId

Yes

Partner-generated unique ID for this decision. Used for audit trail and reconciliation.

decision

Yes

"APPROVE", "DECLINE", or "PASS". Any other value is treated as an error (UR declines).

paidCurrency

On APPROVE

The currency to debit from the funding source that decision selected (ISO symbol, e.g. "USD", "EUR"). On APPROVE, it names a currency in your Prefund Account. On PASS, it names a currency in the user's UR fiat balance; leave it empty to let UR select the currency for you. Not used on DECLINE. See the mode tables in §4.6 examples for every valid combination.

Decision semantics

decision

Effect

APPROVE

Settle against the Prefund Account in paidCurrency. UR still performs final checks and may override to DECLINE.

DECLINE

Reject the authorization entirely. The card swipe is declined.

PASS

Skip double booking for this swipe. UR falls back to the user's own UR fiat balance; the swipe behaves as if the user were on Card Mode: Fiat Only. No Prefund debit occurs; no Partner-side crypto debit is needed.

PASS is useful when the Partner wants to selectively route certain transactions to the user's own balance; for example, small transactions below a threshold, or when the user has sufficient fiat balance and the Partner prefers not to consume Prefund capacity.

Important behavior:

  • UR retains final authority: even after an APPROVE, UR performs balance / limit / compliance / Prefund availability checks and can still decline.

  • Increment consistency: for action: INCREMENT, the Partner must return the same decision and paidCurrency as the original AUTHORIZE for the same transaction. UR rejects currency changes mid-transaction. If the original was PASS, the increment must also be PASS.

  • Fixed mode simplification: in fixed mode, the settlement.amount in the request already includes FX fees. The Partner only needs to check if the Prefund Account can absorb that amount and approve or decline. PASS is also available in fixed mode if the Partner wants to route specific transactions to the user's balance.

Examples by settlement mode

Your settleMode changes only what you may return on APPROVE. PASS and DECLINE behave identically in both modes. The following tables list every valid combination.

Fixed mode. UR pre-computes the debit, so you never run a currency conversion:

decision

paidCurrency

What UR does

APPROVE

Equal to settlement.currency from the request

Debits settlement.amount from your Prefund Account. That amount already includes FX spread and interchange.

APPROVE

Any other currency

Declines the swipe. In fixed mode you cannot choose the debit currency.

APPROVE

Empty

Declines the swipe. paidCurrency is required on APPROVE.

PASS

Empty

Settles from the user's UR fiat balance and selects the currency for you. Your Prefund Account is untouched.

PASS

A currency the user holds

Settles from that currency of the user's UR fiat balance. Declines if that balance is short.

DECLINE

Empty

Declines the swipe.

Partner controlled mode. You choose the Prefund currency, so UR cannot pre-compute the debit:

decision

paidCurrency

What UR does

APPROVE

Any currency your Prefund Account holds

Debits that currency from your Prefund Account. UR applies FX spread and interchange at execution.

APPROVE

A currency your Prefund Account does not hold

Declines the swipe.

APPROVE

Empty

Declines the swipe. paidCurrency is required on APPROVE.

PASS

Empty

Settles from the user's UR fiat balance and selects the currency for you. Your Prefund Account is untouched.

PASS

A currency the user holds

Settles from that currency of the user's UR fiat balance. Declines if that balance is short.

DECLINE

Empty

Declines the swipe.

4.7 Fail-safe semantics

UR treats the following as DECLINE (the Partner's authorization endpoint is considered unavailable):

Failure
UR action

HTTP timeout (no response within 500 ms)

Decline with internal reason partner_timeout

HTTP 5xx

Decline with internal reason partner_5xx

HTTP 4xx

Decline with internal reason partner_4xx (likely Partner config error; investigate)

Invalid or missing signature on response

Decline with internal reason partner_sig_invalid

requestId mismatch

Decline with internal reason partner_invalid_response

Missing decisionId

Decline with internal reason partner_invalid_response

Invalid decision value

Decline with internal reason partner_invalid_response

decision: APPROVE but paidCurrency missing

Decline with internal reason partner_invalid_response

Unsupported paidCurrency

Decline with internal reason partner_invalid_response

Response body exceeds 64 KB

Decline with internal reason partner_invalid_response

Partner signature deadline expired or too far in the future (> 5 min)

Decline with internal reason partner_sig_invalid

UR exposes the internal decline reason on the post-swipe transaction webhook (§5.4) for reconciliation.

Operational note on the authorization URL. The Partner-hosted authorization URL is registered with UR during onboarding. To update it (e.g. environment migration), coordinate the change with UR; there is no self-serve endpoint for this.

For Partners who include a reason field in their response (optional, for reconciliation/analytics).

reason

When to use

ok

Approve.

insufficient_user_crypto

User does not have enough crypto on the Partner side.

insufficient_partner_prefund

Partner's Prefund Account is too low.

user_blocked

Partner-side compliance block.

merchant_blocked

Partner-side MCC / merchant block.

card_disabled

Card is locked or frozen on the Partner side.

internal_error

Catch-all decline; treat as transient.

4.9 Fixed mode: FX quote details

In fixed mode, UR pre-calculates the settlement.amount using on-chain FX rates from the card authorization contract. The calculation mirrors the contract's actual debit logic to ensure the quoted amount matches the on-chain settlement:

  • Same-currency (e.g. Prefund is USD, settlement is USD): settlement.amount = network settlement amount, no FX.

  • Cross-currency (e.g. Prefund is EUR, settlement is USD): UR calls the contract's getRate and getSpread view functions to compute the exact amount including FX spread and interchange fees.

The quoted amount is deterministic at the time of the authorization request. Between the quote and the on-chain settlement (typically < 1 second), exchange rates may shift marginally. This is operationally acceptable for the card authorization use case.

Partners in fixed mode do not need to perform any FX calculation; the settlement.amount is ready to use for balance checks and ledger entries.


5. Card Mode webhooks

UR delivers Card Mode events via the standard webhook envelope. The Partner must verify every webhook signature before acting on it.

5.1 Webhook envelope

5.2 Signature verification

UR signs webhook bodies with EIP-191. Verification steps:

  1. Read the exact raw request body string (do not re-serialize).

  2. Recover the signer address using the body and X-Api-Signature.

  3. 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.

5.3 Retry and idempotency

  • The Partner should return HTTP 200 within 10 seconds.

  • UR retries non-200 / timed-out webhook deliveries up to 3 times, with a 5-minute interval.

  • Use data.id as the idempotency key for card payment transaction_v2 events.

5.4 Card payment transaction (event: "transaction_v2")

UR sends transaction_v2 when a card payment transaction reaches a terminal state. Card payment records use data.type = "MARQETA_AUTHORIZE". The same event covers successful and failed card payments.

Confirmed payment example:

Failed payment example:

Key fields for Crypto Backed reconciliation:

Field
Description

id

UR transaction record ID. Use this field as the idempotency key for transaction_v2 delivery.

type

Card payment transactions use MARQETA_AUTHORIZE.

status

Terminal transaction status, such as CONFIRMED or FAILED.

direction

OUT for card spend.

amount / currency

Amount and currency recorded on the transaction row.

txHash

On-chain transaction hash when available.

detailsJson

Stringified JSON with card payment details. Parse this value before reading nested fields.

detailsJson may include the following card payment fields:

Field
Description

authorizationId

Card authorization identifier.

balance

Balance value recorded with the card payment.

cardCurrency

Card currency.

cardId

Card identifier.

city

Merchant city.

country

Merchant country.

mcc

Merchant category code.

merchant

Merchant display name.

merchantId

Merchant identifier.

settlementAmount

Settlement amount recorded for the card payment.

settlementCurrency

Settlement currency recorded for the card payment.

transactionAmount

Merchant transaction amount.

transactionCurrency

Merchant transaction currency.

reason

Failure reason. This field appears only when the card payment record includes a reason.

Partner crypto-debit responsibility. When a Crypto Backed card payment succeeds, the partner is responsible for computing and debiting the corresponding user crypto amount in its own system. UR reports the card payment transaction data; UR does not move user crypto on the partner's behalf.

Use transaction_v2 records with data.type = "MARQETA_AUTHORIZE" and data.status = "FAILED" for failed card payments. The failure reason is in detailsJson.reason when UR has one.

5.5 Prefund balance alert (event: "prefund.balance.alert")

UR emits prefund.balance.alert when the balance of one settlement currency in your Prefund Account crosses a threshold. Use it as a passive trigger to top up before authorizations start to decline.

The alert is per currency, not per account. If two currencies cross a threshold, UR sends two events.

Example:

Fields:

Field
Description

partnerId

Partner identifier registered with UR.

account

On-chain address of the Prefund Account (Mantle).

currency

The settlement currency this alert is about.

balance

Balance in that currency at the moment the level changed.

minBalance

The threshold configured for that currency.

previousLevel

The level before this change.

level

The level after this change: "normal", "warning", or "critical".

updatedAt

Unix seconds, the balance update that triggered the alert.

When UR sends it. The alert is edge-triggered: UR sends it only when level changes for a currency, not repeatedly while the balance sits below the threshold. You therefore receive an alert on the way down (normal to warning, warning to critical) and again on recovery (back to normal), and nothing in between.

How to handle it:

  • Treat the alert as a trigger, not as truth. Call Get Prefund balance to confirm the current state before you top up; webhook payloads are eventually consistent.

  • Top up that currency. A warning on one currency says nothing about the others.

  • Idempotency key: account + currency + updatedAt. Retry and delivery semantics follow §5.3.

  • A critical level means the next swipe in that currency is at real risk of declining. Treat it as a page, not a ticket.


6. Implementation checklist

Before going live with Card Mode: Crypto Backed:

Prefund operations

  • Confirm the off-ramp chain, the deposit currency, your settlement currency, and the minimum balance (all agreed during onboarding).

  • Confirm your Prefund Account details with UR, and use them as the off-ramp target account.

  • Implement recurring off-ramp automation with an SLA aligned to your minimum-balance buffer.

  • Build an operational dashboard that polls GET /prefund-balance and surfaces level transitions.

  • Subscribe to prefund.balance.alert (§5.5) and route it to your ops channel. Alerts are per currency.

Card Authorization callback

  • Host the authorization endpoint at the URL registered with UR (see the operational note in §4.7).

  • Verify every inbound request's EIP-191 signature against UR's public key before doing any business logic.

  • Implement the handler with a p99 < 500 ms budget. Pre-compute everything you can; avoid cross-region database calls in the hot path.

  • Decide decision deterministically. Return APPROVE to settle from your Prefund Account, PASS to fall back to the user's own UR fiat balance, or DECLINE to reject the swipe. See Examples by settlement mode for every valid decision and paidCurrency combination.

  • Make the handler idempotent on requestId. UR may retry on transient network errors, and you must return the same decision for the same requestId.

  • Build a fail-safe path: if any internal dependency fails, return decision: "DECLINE" with a reason rather than a 5xx. UR treats a 5xx as a decline anyway, but an explicit decline preserves the reason for reconciliation.

Post-swipe + reconciliation

  • Subscribe to the transaction_v2 webhook (§5.4) and verify its signature.

  • When you returned APPROVE and the swipe settled against your Prefund Account, perform the user-side crypto debit once the transaction_v2 webhook reports status: CONFIRMED. Record it against the same requestId.

  • Handle the override case: you returned decision: APPROVE, but UR still declined the swipe. Clean up any speculative Partner-side state.

  • Decide your refund policy and document it for end users.

Operational

  • Treat webhook delivery as at-least-once and implement idempotency on data.id (transactions) and account + currency + updatedAt (Prefund alerts).

  • Maintain monitoring on Partner-side authorization handler latency, success rate, and decline reason distribution.


7. Reference docs

Last updated