Skip to main content
The Card Issuer Program lets your platform issue Visa virtual cards to your end customers. Yativo handles the card network, compliance, and settlement — your backend drives the entire flow via API.
Two API namespaces — keep them separate.The /v1/customers/* path is WaaS (wallet sub-accounts for crypto deposits/withdrawals). It has nothing to do with card customers. Do not mix them up.

Identity Model

  • You are a Yativo user who has been approved into the Card Issuer Program.
  • Your Customers are the end users of your platform who get a card. They are never authenticated directly against Yativo — all API calls come from your backend using your token.
  • yativo_card_id is the primary identifier for a card customer. Store it after onboarding.
  • external_customer_id is your own reference ID — pass it at onboarding and use it to look up the customer later without storing Yativo IDs.

Flow Overview


Step 1 — Check Eligibility

Confirm your account has been granted access before applying.
Response
If eligible is false, contact your account manager. This gate is admin-only — there is no API call to change it yourself.

Step 2 — Apply

Funding Structures

Response

Step 3 — Check Program Status

Applications are reviewed within 1–2 business days. Poll until status is approved.
Approved
On approval, Yativo provisions your master wallet set:
  • SOL deposit address (sol.address) — send USDC on Solana here to top up your USD balance.
  • USD balance — funded automatically when your SOL deposit confirms.
  • EUR balance — funded by swapping from USD.
  • GBP balance — funded by swapping from USD.
Balances update in real time. You never interact with the underlying settlement infrastructure directly.

Step 4 — Fund Your Master Wallet (master_wallet programs only)

Get your current balances and deposit addresses:
Response
Send USDC on Solana to sol.address. Once the deposit confirms, your usdc balance increases automatically. Swap to eur or gbp before funding customers who hold those card currencies.

Swap Currencies

If your customers are in the EU or UK, swap USDC into the correct card currency before funding:
Response
Card currency is determined by the cardholder’s country: UK → GBP, EU → EUR, all others → USD.

Step 5 — Onboard a Customer

Start the onboarding flow for each end customer. Only email is required.
Response 201
Store yativo_card_id — it is the primary path parameter in every subsequent customer call. It is different from customer_id.Do not use your own issuer email as a customer email. Each customer must have a unique email address.
A 6-digit OTP is sent to the customer’s email automatically.

Step 6 — Verify OTP

Collect the OTP from your customer and submit it:
Response 200
Every error response with these codes includes a data.next_step field and a data.action URL pointing to the exact endpoint to call next.

Resend OTP


Generate a verification URL for this customer:
Response
Redirect the customer to kyc_url, or embed the KYC flow in your app using the Sumsub SDK with sumsub_sdk_token. Add ?refresh=true to generate a new link if the existing one has expired.

Step 8 — Poll KYC Status

Approved
Pending
Rejected
Poll every 10 seconds for up to 10 minutes. When next_step is retry_kyc, fetch a fresh kyc-link?refresh=true and redirect the customer.
After KYC approval, you must call both of these endpoints before creating a card — regardless of whether the background operations appear to have succeeded:1. Accept terms:
Works for both own-account and customer cards — supply the customer’s yativo_card_id as the path parameter. This is idempotent. Skipping it causes LEGAL_ACCEPTANCE_REQUIRED at card creation.2. Confirm Safe deployment:
Even when the platform auto-deploys the Safe in the background, card creation checks the local DB state, not the card network directly. Calling this endpoint syncs the deployment status to the DB. You will typically receive "already_deployed": true (meaning the card network already has it — this call just ensures the DB record is updated). Skipping it causes SAFE_NOT_DEPLOYED at card creation.Both calls are idempotent. Call them in order after KYC approval, then proceed to Source of Funds.

Step 9 — Source of Funds

Get questions

Response

Submit answers

Response

Step 10 — Phone Verification

Request SMS code

Response

Verify SMS code

Response

Step 11 — Create Virtual Card

All prerequisites are complete. Issue the card:
Response 201
To show the customer their full card number and CVV, request a secure view URL (see Secure Card View below) and open it in an iframe or WebView.

Multiple Cards per Customer

A single customer account supports up to 5 active cards (virtual + physical combined). You can issue additional virtual cards on top of the first one, subject to the limits set on your program.
The response is identical to the first card creation. Each call issues a new independent card on the same customer account. If the customer has reached their limit you will get:
403 Limit reached

Card Limits

Limits work in a three-tier hierarchy:
The defaults on a new program are 1 virtual, 1 physical, 2 total per customer.

Set per-customer limits (issuer)

Override the limit for a specific customer, up to your program’s ceiling:
All fields are optional — send only the limits you want to change.
Response 200
program_ceilings reflects the maximum values your program permits. You cannot set a customer limit above its corresponding ceiling.

Step 12 — Fund the Card

Option A: Push from Master Wallet (master_wallet programs)

You can identify the customer by any of: customer_id, card_id, external_id, email, or yativo_card_id.
Response 200
Save the transfer_id. Poll GET /v1/card-issuer/transfers/:transferId until status is completed (typically 2–5 minutes). pricing_mode:
  • receive_x — the customer receives exactly amount. Yativo deducts slightly more from your master wallet to cover fees.
  • send_x (default) — exactly amount is debited from your master wallet. The customer receives less after fees.
TOKEN_MISMATCH error: if you fund with the wrong currency for a customer’s card region, the API returns this error with the exact token their card requires. Swap your master wallet balance first.

Option B: Customer Self-Funds via Deposit Address (non_master programs)

Get the customer’s deposit address:
Response

Card Management

List all customers

Response
Filter by flow_status: otp_requested, otp_verified, kyc_initiated, kyc_completed, card_created, active.

Look up a customer

Find a customer by any identifier:
Supported query parameters (pass exactly one):
Response

Freeze / Unfreeze a Card

Response
Response

Get Card Transactions

Response

Spending Limits

Get the current spending limit for a customer’s card:
Response
Update the daily spending limit:
Response
Limit changes go through a Gelato relay with a 3-minute processing delay. The gelato_status: "ExecSuccess" confirms the transaction was enqueued. Poll GET /wallet/limits after 3 minutes to confirm the new limit is active.

Secure Card View

To let a cardholder view their full card details (PAN, CVV, expiry, PIN), your backend requests a secure view URL from Yativo. You send that URL to your customer — via your app, an email link, or an in-app iframe. Yativo hosts the page and handles all cryptography internally. Your backend never sees or handles raw card data.

How it works

No SDK integration is required on your side. Yativo handles all the cryptography and secure rendering.

Request a secure view URL

Response
Open secure_view_url in a browser tab, iframe, or mobile WebView. The URL is short-lived. Request a new one each time the customer wants to view their card. The response includes pin_set — the last known state from the physical.card.pin.changed webhook. Use it in your UI to decide whether to prompt the customer to set their PIN before showing card details.

Customer PIN setup and change

Every card starts with pin_set: false. The customer must set a PIN before chip-and-PIN or ATM transactions will work. Use the same view-token endpoint with enabled_views: ["pin"] to show the PIN setup page — this also handles PIN changes.
Open the returned secure_view_url for your customer in an iframe or WebView. The cardholder enters their 4-digit PIN directly in the hosted page — it never passes through your backend. Once saved, the card network fires a physical.card.pin.changed webhook and Yativo updates pin_set: true on the card record.
pin_set is sourced from the webhook, not from a direct card network API lookup. Use it as a UI hint to prompt customers who haven’t yet set a PIN — not as a hard access gate.

Deposits

View all funding deposits into your issuer program (SOL auto-funding and XDC manual deposits):
Filter by status: pending, auto_funding, awaiting_manual, funding, funded, failed. Filter by chain: SOL, XDC.

Transfers

All transfers

View all funding transfers you have sent to customer cards:
Response
Supports status, customer_id, and chain query filters. See List Transfers.

Single transfer or withdrawal status

Accepts either a funding transfer_id or a withdrawal’s withdrawal_id — checks funding transfers first, falls back to withdrawals. The response’s type field ("funding" or "withdrawal") tells you which one matched. See Get Transfer Status for the full response shape and status enum.

Transfers for a specific customer

customerId accepts yativo_card_id, customer_id, or your own external_id. See List Customer Transfers.

Check Progress Anytime

Response

Delete an Incomplete Customer Record

If you created a customer by mistake (e.g. wrong email) and the card has not yet been issued:
This endpoint is blocked once the customer reaches card_created or active status.

Reset Customer Onboarding

If a customer’s onboarding is stuck (KYC rejected multiple times, verification loop, wrong details submitted) and you need to start completely fresh, use the reset endpoint. This deletes the Yativo record and allows re-onboarding with a new verification flow.
Response 200
You must use a different email address when re-onboarding. The previous email remains registered with the card network and cannot be reused for a new account. Attempting to re-onboard with the same email will fail with EMAIL_ALREADY_REGISTERED.
When reset is blocked: As an issuer, you can only reset a customer who has not yet had a card issued. Once the customer reaches card_created status, this endpoint returns:
400 Card already issued
If you need to reset a customer who already has a card, contact Yativo support — admin-level resets are available for exceptional cases.

Webhook Events

Subscribe to webhooks for real-time events. See Webhook Events for payload examples, signature verification, and the full event reference.
KYC status changes are not delivered as webhooks — poll Get Customer or Look Up Customer to check kyc_status after directing customers through the KYC link.


Recovery & Continuation Reference

Every operation that can fail returns a data.next_step field and a data.action URL so you never have to guess what to do. This section documents every failure mode and the exact API call that recovers from it.

Onboarding State Machine


Handling All Error Codes

OTP Phase errors

All OTP errors include data.attempts_remaining, data.next_step: "resend_otp", and data.action in the response body.

KYC Phase errors


Abandoned Onboardings — resume Endpoint

If a customer starts onboarding but never finishes (OTP not verified, KYC link never opened, KYC in progress for days), call the resume endpoint. It inspects the current state, takes the correct action automatically, and tells you exactly what to present to the customer next.
What it does by state:
Response — OTP phase
Response — KYC phase
Use days_since_created to decide how aggressively to pursue a customer. A 1-day abandoned onboarding is worth a simple email nudge; a 30-day one may warrant re-onboarding from scratch.

Polling Strategy

For KYC status polling, use an exponential-backoff approach with a hard timeout:
When kyc_status === 'rejected', fetch a fresh KYC link and redirect the customer:

Full next_step Reference

Every API response in the customer lifecycle includes data.next_step. Use it to drive your state machine without hardcoding assumptions about flow order.

Common Integration Mistakes

Do not hardcode state transitions. Always read next_step from the response. States can be added between releases.

Handling INITIALIZATION_FAILED on Onboard

POST /customers/onboard performs several steps internally (wallet generation, SIWE signing, OTP request, DB write). In rare cases — typically a transient database timeout or network issue — the API returns 500 INITIALIZATION_FAILED even though the customer record was successfully created and the OTP email was already sent. Recovery pattern: Retry the onboard call with the same email (and external_customer_id if you use one). One of two things will happen:
  1. Success (201) — the first call truly failed end-to-end. A fresh customer record is created.
  2. CUSTOMER_CARD_ALREADY_ACTIVE (409) — the first call partially succeeded. The response includes the yativo_card_id and next_step so you can pick up exactly where you left off:
409 CUSTOMER_CARD_ALREADY_ACTIVE
Use the returned yativo_card_id to call POST /customers/{yativoCardId}/verify-otp (the OTP email was already delivered on the first call). Do not treat CUSTOMER_CARD_ALREADY_ACTIVE as an error — it is the system telling you the card exists and showing you how to continue.

Quick Reference

Issuer Program (/v1/card-issuer/*)

Card Customer Lifecycle (/v1/yativo-card/customers/*)