IZ IZIPAY Business API
Get API access
API Reference

IZIPAY Business API

Issue virtual cards for your users programmatically, fund them with crypto, and track everything in real time. A single REST API with predictable JSON responses and webhook events.

Base URL https://izipay.me/api/v1

The API speaks JSON over HTTPS. Every request must be authenticated with a Bearer token. All responses share a consistent envelope with a top-level success flag.

Authentication

Authenticate every request by sending your secret API key in the Authorization header as a Bearer token.

Header
Authorization: Bearer YOUR_API_KEY
!
Keys prefixed with izpk_live_ are live keys tied to real card issuance and payments. Treat them like passwords: never expose them in client-side code or public repositories, and rotate them periodically from your dashboard.

Requests without a valid key return 401 INVALID_AUTH.

Request signing (optional, recommended)

Each key has a secret (izps_…, shown once when the key is created). Sign requests with it so that a leaked API key alone is useless. Enable it per key in the cabinet (API keys → Signing): while optional, a signature is verified only when sent; when required, unsigned requests return 401.

Headers
X-Timestamp: 1725465600 # unix seconds, within ±5 min of server time X-Signature: <hex HMAC-SHA256> # over: timestamp + "\n" + METHOD + "\n" + path_with_query + "\n" + raw_body
Node.js
const ts = Math.floor(Date.now() / 1000).toString(); const sig = crypto.createHmac('sha256', SECRET).update(`${ts}\n${method}\n${pathWithQuery}\n${rawBody}`).digest('hex'); headers['X-Timestamp'] = ts; headers['X-Signature'] = sig;

Example string to sign for GET /api/v1/cards?limit=50: "1725465600\nGET\n/api/v1/cards?limit=50\n" (empty body). Every signature is accepted once (replay protection). Keys created before September 2026 cannot enable signing — create a new key.

Quickstart

The typical flow to put a funded card in your user's hands is four steps:

1Issue a card — call POST /cards/issue with the cardholder's email. You receive a crypto deposit address.
2Collect payment — have your user send the exact pay_amount to the returned deposit_address.
3Wait for issuance — once payment confirms, the card is provisioned automatically.
4Receive a webhook — a card.issued event is delivered to your registered endpoint.

Sandbox (testing)

Build and test your entire integration with zero real crypto and zero real cards. Use a test API key (starts with izpk_test_) — every call is mocked and isolated from production. When you're ready, switch to your live key (izpk_live_) and nothing else changes.

Get a test keyAsk your account manager for a sandbox key (izpk_test_…). Same endpoints, same auth.
Issue / top upWith a test key, POST /cards/issue and /topup return a fake deposit_address and payment_id, and the response includes "sandbox": true. No crypto is expected and no real card exists.
Simulate paymentCall POST /sandbox/confirm with the payment_id to instantly "pay". A fake test card is provisioned (test BIN 4111…) or the top-up is credited, and the same webhooks fire (card.issued, topup.completed).
Go liveReplace the test key with your live key. Test cards (BIN 4111) can never be used for real spending.
1 · Issue in sandbox
curl -X POST https://izipay.me/api/v1/cards/issue \ -H "Authorization: Bearer izpk_test_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "cardholder_email": "alice@example.com" }' # → { "data": { "card_id": "card_test_...", # "sandbox": true, # "payment": { "payment_id": "gwtest_...", # "deposit_address": "TEST...", ... } } }
2 · Simulate the payment
curl -X POST https://izipay.me/api/v1/sandbox/confirm \ -H "Authorization: Bearer izpk_test_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "payment_id": "gwtest_..." }' # → { "data": { "issue_status": "issued", # "card": { "number": "4111111111116204", # "exp": "07/29", "cvv": "123", "last4": "6204" } } }
i
Sandbox is fully isolated: no HD deposit address is consumed, no crypto is watched, and no card is issued through the provider. You can create unlimited test cards at no cost — they are fake and cannot spend.

Card types

You can issue three kinds of cards. Pick one per request with the card_type field on POST /cards/issue (defaults to visa).

 card BIN 4004 (card_type: visa)Mastercard BIN 5378 (card_type: mastercard_standard)Apple Pay Mastercard (card_type: mastercard)
Issue priceYour account's card priceSame as visaYour account's Apple Pay price (default $20)
FundingBalance or cryptoBalance or cryptoBalance or crypto (not the prepaid pool)
Top-up fundingCrypto or account balanceCrypto or account balanceCrypto (USDT TRC-20) or account balance
Top-up feeYour top-up rate + network feeSame rate as visa + network feeYour top-up rate (default 3%) + a fixed $1.70 network fee — same for crypto and balance
Apple Pay / Google PaySupportedNot supported (online payments only)Supported (this is the recommended card for wallets)
i
Bank spending fees (Apple Pay Mastercard only). The issuing bank charges the cardholder a small fee on each purchase, deducted automatically from the card balance: 1% on cross-border transactions, $0.30 on transactions under $50, and 0.2% on Apple Pay payments. Declined transactions are never charged. These fees come out of the card's own balance — you are not billed for them. They appear as separate fee lines in GET /cards/{card_id}/transactions.
i
Aliases accepted for card_type: visa for the online-payment card BIN 4004, mastercard_standard / 5378 for the Mastercard BIN 5378, and apple_pay / mastercard for the Apple Pay Mastercard.

Issue a card

POST/cards/issue

Creates a new card for one of your end-users and returns a crypto deposit address. The card is provisioned automatically once the payment is received on-chain. To pay from your account balance instead of crypto, send "pay_currency": "balance" — the card is charged instantly with no on-chain step. See Card types to choose between card and Apple Pay Mastercard.

Body parameters

FieldTypeRequiredDescription
cardholder_emailstringrequiredThe end-user's email address.
card_typestringoptionalWhich card to issue: visa (default, BIN 4004), mastercard_standard (Mastercard BIN 5378, same price as visa, no Apple Pay) or mastercard (Apple Pay Mastercard, priced at your account's Apple Pay rate, default $20). See Card types.
cardholder_aliasstringoptionalDisplay name. Defaults to the email prefix.
client_card_refstringoptionalYour own reference for this card (e.g. your internal user ID). Echoed back in webhooks.
pay_currencystringoptionalHow to pay for the card. Defaults to usdttrc20. Use balance to charge your account balance instantly (no crypto step). Also accepts usdterc20, usdcerc20, and others.

Headers

X-Idempotency-KeyrecommendedA unique string per logical request. Retrying with the same key never issues a second card.
Request
curl -X POST https://izipay.me/api/v1/cards/issue \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -H "X-Idempotency-Key: unique-request-id" \ -d '{ "cardholder_email": "alice@example.com", "cardholder_alias": "Alice", "client_card_ref": "user_42" }'
Response · 200
{ "success": true, "data": { "card_id": "card_abc123def456", "issue_status": "pending_payment", "payment": { "provider": "izipay_gateway", "deposit_address": "TKhWqGZ...", "pay_amount": 50, "pay_currency": "usdttrc20", "network": "trc20", "amount_usd": 50, "expires_at": "2026-05-22T09:04:20Z" } } }

Example · Apple Pay Mastercard, paid from balance

Request
curl -X POST https://izipay.me/api/v1/cards/issue \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "cardholder_email": "bob@example.com", "card_type": "mastercard", "pay_currency": "balance" }'
Response · 201
{ "success": true, "data": { "card_id": "card_9f2a...c1", "issue_status": "paid_pending_issue", "card_type": "mastercard", "provider": "izipay_gateway", "funded_from": "balance", "price_paid_usd": 30, "balance_usd": 470.00 } }
i
An Apple Pay card is provisioned by the issuer a few minutes after issuance. Poll GET /cards/{card_id} until issue_status becomes issued, or listen for the card.issued webhook. If the issuer ever rejects the card, a balance-funded charge is refunded automatically.

Get card details

GET/cards/{card_id}

Retrieves the current state of a card, including its masked number, balance, and issuance status.

Request
curl https://izipay.me/api/v1/cards/card_abc123def456 \ -H "Authorization: Bearer YOUR_API_KEY"
Response · 200
{ "success": true, "data": { "card_id": "card_abc123def456", "card_number": "5258 47** **** 1937", "balance": 100.00, "issue_status": "issued", "payment_status": "paid", "issued_at": "2026-05-22T08:15:00Z" } }

List cards

GET/cards

Returns all cards you have issued, most recent first, with pagination.

Query parameters

FieldTypeRequiredDescription
pageintegeroptionalPage number, starting at 1. Default 1.
limitintegeroptionalCards per page. Default 100.
statusstringoptionalFilter by issue status, e.g. issued, pending_payment.
Request
curl https://izipay.me/api/v1/cards?limit=2 \ -H "Authorization: Bearer YOUR_API_KEY"
Response · 200
{ "success": true, "data": { "cards": [ { "card_id": "card_abc123def456", "client_card_ref": null, "cardholder_email": "user@example.com", "issue_status": "issued", "payment_status": "paid", "balance": 100.00, "pending_topup": 0.00, "is_frozen": false, "created_at": "2026-05-22T08:15:00Z", "issued_at": "2026-05-22T08:15:05Z" } ], "page": 1, "limit": 2, "total": 128, "total_pages": 64 } }

Top up a card

POST/cards/{card_id}/topup

Requests a balance top-up for an existing card. Returns a payment invoice, the same way card issuance does.

Body parameters

FieldTypeRequiredDescription
amount_usdnumberrequiredAmount to add to the card balance, in USD.
pay_currencystringoptionalHow to fund the top-up. Defaults to usdttrc20 (crypto — returns a deposit address to send USDT to). Use balance to charge your prepaid account balance instantly, with no on-chain step — works for any card (Visa or Mastercard). Also accepts usdterc20, usdcerc20, and others.
Request
curl -X POST https://izipay.me/api/v1/cards/card_abc123/topup \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount_usd": 100, "pay_currency": "usdttrc20" }'
i
The response returns a deposit_address and the exact pay_amount in crypto your customer must send. A commission (your account's top-up rate) is deducted, so amount_on_card is what actually lands on the card. The card is credited automatically once the payment confirms on-chain.
Request — from account balance (instant, no crypto)
curl -X POST https://izipay.me/api/v1/cards/card_abc123/topup \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount_usd": 100, "pay_currency": "balance" }'
i
Fund from your account balance (any card). With "pay_currency": "balance" the card is credited instantly from your prepaid balance — no deposit address, no on-chain wait. The response returns status: "credited" and funded_from: "balance". Your balance is debited by amount_usd; amount_on_card is what lands after your top-up fee and network fee. Because your account balance itself can be funded with any crypto (auto-converted to USD), this is usually the simplest way to fund cards.
i
Apple Pay Mastercard top-ups. A mastercard card can be topped up two ways, both with a flat 3% fee and a $5 minimum:
  • From your balance"pay_currency": "balance". Credited instantly, no deposit address. A network fee applies because your funds are swept from your deposit wallet: $1.70 if they sit on TRON, $0.50 on BEP-20 / ERC-20 / Polygon (pass "network" to say where your deposit is held). So a $100 top-up lands $95.30. Since your account balance can be funded with any crypto (auto-converted to USD), this is the simplest way. Response: status: "credited".
  • Direct crypto"pay_currency" one of usdttrc20, usdtbep20, usdterc20, usdtpoly (USDT on TRON, BNB Smart Chain, Ethereum or Polygon). Network fee: $1.70 on TRON (a $100 top-up lands $95.30), $0.50 on BEP-20, ERC-20 and Polygon (a $100 top-up lands $96.50). Credited after the payment confirms on-chain.
The response includes card_type: "mastercard", fee_pct and amount_on_card. Bank spending fees are charged separately per purchase — see Card types.

Return card balance

POST/cards/{card_id}/return

Moves unspent funds from a card back to your account balance. Use it before retiring a card, or to reclaim liquidity. The returned amount lands on your account balance and can be reused to issue or top up other cards.

Body parameters

FieldTypeRequiredDescription
amount_usdnumber | stringoptionalAmount to return, in USD. Pass "all" to return the entire available balance (default).
Request
curl -X POST https://izipay.me/api/v1/cards/card_abc123/return \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount_usd": "all" }'
Response · 200
{ "success": true, "data": { "card_id": "card_abc123", "status": "returned", "amount_returned": 42.15, "card_balance": 0.00, "balance_usd": 382.70 } }
i
Requests are idempotent per card while a return is in flight. If the card balance is lower than the amount requested, the call returns INSUFFICIENT_CARD_BALANCE (402) and no funds are moved.

Transfer between cards

POST/cards/{card_id}/transfer

Moves funds directly from one of your cards to another of your cards. No fee — the money never leaves the system, so this is free (unlike a return followed by a top-up, where the top-up commission applies). Both cards must be issued and belong to your account. {card_id} in the path is the source card.

Body parameters

FieldTypeRequiredDescription
to_card_idstringrequiredDestination card id (must differ from the source and belong to your account).
amountnumberrequiredAmount to move, in USD. Must not exceed the source card's available balance.
Request
curl -X POST https://izipay.me/api/v1/cards/card_abc123/transfer \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -H "X-Idempotency-Key: unique-key-123" \ -d '{ "to_card_id": "card_def456", "amount": 50.00 }'
Response · 200
{ "success": true, "data": { "from_card_id": "card_abc123", "to_card_id": "card_def456", "amount": 50.00, "fee": 0.00, "amount_credited": 50.00, "from_balance": 120.00, "to_balance": 80.00, "reference_id": "…" } }
i
Pass X-Idempotency-Key to make retries safe — a repeat with the same key returns the original result instead of transferring again. If the destination step fails, the source card is restored automatically and no funds are lost.

Get transactions

GET/cards/{card_id}/transactions

Returns the spending and top-up history for a card, most recent first.

Request
curl https://izipay.me/api/v1/cards/card_abc123/transactions \ -H "Authorization: Bearer YOUR_API_KEY"
Response · 200
{ "success": true, "data": [ { "type": "purchase", "amount": -12.40, "merchant": "Spotify", "date": "2026-05-23T10:11:00Z" }, { "type": "topup", "amount": 100.00, "date": "2026-05-22T08:30:00Z" } ] }

Verification codes — Apple Pay / Google Pay & 3-D Secure

POST/cards/{card_id}/apple-pay-code

When a cardholder adds an Apple Pay Mastercard to their wallet, the issuer sends a one-time verification code by email. This endpoint captures that code and returns it to you. Only Mastercard (Apple Pay / Google Pay) cards use codes — Visa cards do not.

Two steps. First POST to arm the card (tell us a code is expected), then add the card to the wallet, and finally receive the code by webhook or by polling GET.

1 · Arm — POST

Request
curl -X POST https://izipay.me/api/v1/cards/card_abc123/apple-pay-code \ -H "Authorization: Bearer YOUR_API_KEY"
Response · 200
{ "success": true, "data": { "card_id": "card_abc123", "status": "armed", "expires_in": 600, "delivery": { "webhook": "card.otp", "poll": "GET /cards/card_abc123/apple-pay-code" } } }

2 · Retrieve — GET (poll)

Request
curl https://izipay.me/api/v1/cards/card_abc123/apple-pay-code \ -H "Authorization: Bearer YOUR_API_KEY"
Response · 200 (delivered)
{ "success": true, "data": { "card_id": "card_abc123", "status": "delivered", "code": "481923", "matched_at": "2026-05-22T08:31:12Z" } }
i
The arm request lives for 10 minutes. While waiting, GET returns status: "waiting". Once the issuer's email arrives it flips to "delivered" with the code, and a card.otp webhook fires. Arm one card at a time — the issuer sends the code without a card number, so a second concurrent request cannot be matched reliably.

3-D Secure — online purchases

This is different from wallet activation. When your cardholder pays at an online merchant that requires 3-D Secure verification, the issuer generates a one-time code for that specific transaction. IZIPAY captures it and pushes it to you automatically on the card.otp webhook — no arming needed. The 3-D Secure code is tied to the exact card, so it is always matched correctly. Just handle the webhook and show the code to your cardholder to complete the payment.

card.otp webhook body — payment_3ds
{ "id": "evt_9f2c8a1b…", "type": "card.otp", "created": 1788169014, "data": { "card_id": "card_abc123", "last4": "3624", "code": "884916", "kind": "payment_3ds" } }
card.otp webhook body — wallet_provision
{ "id": "evt_7a1b5e90…", "type": "card.otp", "created": 1788169100, "data": { "card_id": "card_abc123", "last4": "3624", "code": "481923", "kind": "wallet_provision" } }
i
The kind field separates the two flows: payment_3ds is an online-purchase 3-D Secure code (fires automatically, no arm), and wallet_provision is an Apple Pay / Google Pay activation code (fires after you arm the card above). Every delivery carries headers X-Izipay-Signature (HMAC-SHA256 of the raw body, keyed with your webhook signing secret), X-Izipay-Event and X-Izipay-Delivery-Id — verify the signature before trusting the payload. Codes expire in about 10 minutes, so relay them to your cardholder promptly and return HTTP 200.

Get account balance

GET/balance

Returns summary statistics for your account: cards issued, total volume, and your current prepaid balance.

Request
curl https://izipay.me/api/v1/balance \ -H "Authorization: Bearer YOUR_API_KEY"
Response · 200
{ "success": true, "data": { "cards_issued": 128, "cards_active": 119, "balance_usd": 340.55 } }

Fund the prepaid pool

POST/pool/topup

Pre-pays for a batch of card issuances at your account's card price. Funding the pool up front means later card issuance is drawn from the pool at no extra on-chain step. Pass either a number of cards or a USD amount.

Body parameters

FieldTypeRequiredDescription
cardsintegeroptionalNumber of cards to pre-pay for. The USD amount is cards × card_price.
amountnumberoptionalUSD amount to add to the pool directly. Provide this or cards.
pay_currencystringoptionalSettlement currency. Defaults to usdttrc20. USDT/USDC/native coins on TRC-20, BSC, Ethereum, Polygon, Solana or BTC.
Request
curl -X POST https://izipay.me/api/v1/pool/topup \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "cards": 100, "pay_currency": "usdttrc20" }'
Response · 200
{ "success": true, "data": { "pool_topup_id": "pool_abc123", "cards": 100, "amount_usd": 600.00, "payment": { "deposit_address": "TXs...address", "pay_amount": 600.00, "pay_currency": "usdttrc20", "network": "trc20" } } }
i
The pool is credited automatically once the deposit confirms on-chain. Pool balance is shown in GET /balance. The prepaid pool applies to card issuance; card top-ups are charged separately.

Exchange · list assets

GET/exchange/assets

Your account balance and prepaid pool are spent in USDT on Tron, Polygon or Ethereum only. Anything else you deposit — Bitcoin, Solana, USDC — has to be moved into one of those first. This endpoint lists what you currently hold and where it can go.

Balances are read from the blockchain, so this call takes a few seconds. Cache it rather than polling.

Request
curl https://izipay.me/api/v1/exchange/assets \ -H "Authorization: Bearer YOUR_API_KEY"
Response · 200
{ "success": true, "data": { "assets": [ { "id": "sol", "network": "sol", "ticker": "SOL", "label": "Solana native", "balance": 0.27268135, "balance_usd": 20.00, "unit_usd": 73.35 } ], "targets": [ { "network": "polygon", "currency": "usdtmatic" } ] } }

Not exchangeable: native TRX, ETH, BNB and POL sitting on your addresses. Those are gas we top up ourselves so sweeps can run — they are not part of your balance.

Exchange · quote

GET/exchange/quote

Minimum for a direction and an estimate of what you would receive. Every direction has its own minimum, set by our exchange partner, and it is often higher than a small balance — minimum_usd is returned alongside so you can tell at a glance.

Request
curl "https://izipay.me/api/v1/exchange/quote?from=sol&to_network=polygon&amount=0.5" \ -H "Authorization: Bearer YOUR_API_KEY"
Query parameters
"from" required · id from /exchange/assets "to_network" required · trc20 | polygon | eth "amount" optional · units of the source coin
Response · 200
{ "success": true, "data": { "from": "sol", "to_network": "polygon", "minimum": 0.16042, "minimum_usd": 11.78, "unit_usd": 73.44, "to_amount_estimated": 36.21 } }

Cost varies sharply by destination. Payouts in Tron carry a much larger fixed fee than Polygon — on small amounts the difference can be a third of the sum. Always quote before exchanging.

Exchange · create

POST/exchange

Moves an asset from your address into USDT on the network you pick. There is no destination address field — funds always land on your own deposit address in the target network, so an exchange can never send money anywhere else.

Your USD balance does not change: this moves money between networks, it does not add or remove it. Only the exchange fee is charged, after completion, as a separate swap_cost entry.

Sending runs in the background — it needs gas, and energy rental on Tron — so the response returns immediately with pending. Poll GET /exchange/{order_ref} for progress.

Request
curl -X POST https://izipay.me/api/v1/exchange \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "X-Idempotency-Key: your-unique-id" \ -H "Content-Type: application/json" \ -d "{"from":"sol","to_network":"polygon","amount":0.5}"
Body
"from" required · id from /exchange/assets "to_network" required · trc20 | polygon | eth "amount" required · units of the source coin
Response · 201
{ "success": true, "data": { "order_ref": "SW16AED598FE", "status": "pending", "from": { "currency": "sol", "amount": 0.5 }, "to": { "network": "polygon", "amount_estimated": 36.21 }, "destination": "0xc074c8...10b1" } }

Use X-Idempotency-Key. An exchange cannot be undone. With the key, a retried request returns the original order instead of creating a second one — without it, a network timeout on your side can cost you a duplicate exchange.

Exchange · status and history

GET/exchange/{order_ref}
GET/exchange

Status of one exchange, or your history (newest first, ?limit= up to 200).

status
"pending" created, funds not confirmed yet "paid" partner received, exchanging "done" USDT credited to your address "failed" did not go through "refunded" returned to the source address "expired" order lapsed
send_status · our leg
"queued""sending""sent"
Response · 200
{ "success": true, "data": { "order_ref": "SW16AED598FE", "status": "done", "send_status": "sent", "to": { "amount_estimated": 19.753338, "amount_received": 19.750278 }, "send_tx": "2Dwigm...GXuG", "payout_tx": "0x312ad3...2433" } }

amount_received is what actually arrived; amount_estimated was the quote at creation. The two differ slightly — the difference is the exchange fee and is charged from your balance once, on completion.

Payment gateway · create a payment

POST/payments

The payment gateway lets you accept crypto from your own customers. Create a payment, show the returned address and amount to your customer, and receive funds (converted to USD) into your gateway balance — from which you can pay out. A flat gateway_fee_pct applies; see Gateway balance.

Body parameters

FieldTypeRequiredDescription
price_amountnumberrequiredAmount to charge, in USD.
pay_currencystringrequiredWhat the customer pays in, e.g. usdttrc20, btc, eth. Or pass a base coin (usdt) plus network.
order_idstringoptionalYour reference for the order (≤128 chars).
order_descriptionstringoptionalHuman-readable description (≤255 chars).
ipn_callback_urlstringoptionalURL to receive status callbacks for this payment.
Request
curl -X POST https://izipay.me/api/v1/payments \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "price_amount": 49.99, "pay_currency": "usdttrc20", "order_id": "order-8842" }'
Response · 201
{ "success": true, "data": { "payment_id": "pay_abc123", "order_id": "order-8842", "status": "waiting", "pay_address": "TXs...address", "pay_amount": 49.99, "pay_currency": "usdttrc20", "network": "trc20", "price_amount": 49.99, "expires_at": "2026-05-22T09:15:00Z", "qr_data": "tron:TXs...?amount=49.99" } }

Payment gateway · list payments

GET/payments

Lists gateway payments, most recent first.

Query parameters

FieldTypeRequiredDescription
limitintegeroptionalMax rows (1–200). Default 50.
offsetintegeroptionalRows to skip. Default 0.
statusstringoptionalFilter, e.g. confirmed, waiting.
Response · 200
{ "success": true, "data": { "payments": [ { "payment_id": "pay_abc123", "order_id": "order-8842", "status": "confirmed", "pay_amount": 49.99, "amount_paid": 49.99, "pay_currency": "usdttrc20", "network": "trc20", "price_amount": 49.99, "created_at": "2026-05-22T08:15:00Z", "confirmed_at": "2026-05-22T08:22:00Z" } ], "count": 1, "limit": 50, "offset": 0 } }

Payment gateway · get a payment

GET/payments/{payment_id}

Retrieves the current status of a single gateway payment.

Request
curl https://izipay.me/api/v1/payments/pay_abc123 \ -H "Authorization: Bearer YOUR_API_KEY"
Response · 200
{ "success": true, "data": { "payment_id": "pay_abc123", "order_id": "order-8842", "status": "confirmed", "pay_address": "TXs...address", "pay_amount": 49.99, "amount_paid": 49.99, "pay_currency": "usdttrc20", "network": "trc20", "price_amount": 49.99 } }
i
Statuses: waiting, partially_paid, confirmed, expired, failed, refund_needed.

Payment gateway · balance

GET/gateway/balance

Your gateway balance (customer payments received, net of fees) and lifetime totals. This balance is what you draw from when creating a payout.

Response · 200
{ "success": true, "data": { "balance_usd": 1240.55, "gateway_fee_pct": 1.0, "lifetime": { "total_received_usd": 8600.00, "total_fees_usd": 86.00, "total_paid_out_usd": 7273.45 } } }

Payment gateway · create a payout

POST/payouts

Withdraws funds from your gateway balance to a crypto address you control. The payout is queued and sent on-chain.

Body parameters

FieldTypeRequiredDescription
amount_usdnumberrequiredAmount to withdraw from your gateway balance, in USD.
networkstringrequiredNetwork to send on, e.g. trc20, bsc, polygon, eth.
addressstringrequiredDestination wallet address.
currencystringoptionalAsset to send. Default usdt.
Request
curl -X POST https://izipay.me/api/v1/payouts \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount_usd": 500, "network": "trc20", "address": "TXs...address" }'
Response · 200
{ "success": true, "data": { "payout_id": "payout_abc123", "status": "pending", "amount_usd": 500.00, "network": "trc20", "currency": "usdt", "to_address": "TXs...address", "balance_usd": 740.55 } }

Payment gateway · list payouts

GET/payouts

Lists your payouts, most recent first. Supports limit (1–200, default 50) and offset.

Response · 200
{ "success": true, "data": { "payouts": [ { "payout_id": "payout_abc123", "status": "sent", "amount_usd": 500.00, "network": "trc20", "currency": "usdt", "to_address": "TXs...address", "amount_sent": 500.00, "tx_hash": "a1b2c3...", "created_at": "2026-05-22T08:15:00Z", "processed_at": "2026-05-22T08:20:00Z" } ], "count": 1 } }
i
Payouts are reviewed before they are sent on-chain, so status moves from pending to sent once processed. tx_hash is populated after broadcast.

Webhooks

Register an HTTPS endpoint to receive event notifications as they happen. Events are delivered as POST requests with a JSON body and are retried with backoff if your endpoint does not return 2xx.

Event types

card.createdA card record was created and is awaiting payment.
card.paidThe customer's invoice was paid.
card.issuedThe card was provisioned and is ready to use.
card.failedProvisioning failed; no charge applies.
topup.completedA top-up was applied to a card balance.
card.otpA one-time verification code was captured for a card. Two kinds via the data.kind field: payment_3ds (3-D Secure online purchase — fires automatically) and wallet_provision (Apple Pay / Google Pay activation — after you arm the card). See verification codes & 3-D Secure.
payment.confirmedA payment gateway charge was fully paid and credited to your gateway balance.
payout.sentA gateway payout was broadcast on-chain.
Example payload
{ "id": "evt_abc123", "type": "card.issued", "created": 1733923200, "data": { "card_id": "card_abc123", "card_number": "5258 47** **** 1937", "client_card_ref": "user_42", "cardholder_email": "alice@example.com" } }

Verifying signatures

Each delivery includes an X-IZIPAY-Signature header — an HMAC-SHA256 of the raw request body, signed with your webhook secret. Always verify it before trusting an event.

Node.js
const crypto = require('crypto'); app.post('/webhooks/izipay', (req, res) => { const signature = req.headers['x-izipay-signature']; const expected = crypto.createHmac('sha256', WEBHOOK_SECRET) .update(req.rawBody).digest('hex'); if (signature !== expected) { return res.status(401).send('Invalid signature'); } // Event is authentic — process it res.json({ received: true }); });

List webhooks

GET/webhooks

Returns the webhook endpoints registered on your account.

Request
curl https://izipay.me/api/v1/webhooks \ -H "Authorization: Bearer YOUR_API_KEY"
Response · 200
{ "success": true, "data": { "webhooks": [ { "id": 7, "url": "https://yoursite.com/hooks/izipay", "events": ["*"], "is_active": true, "created_at": "2026-05-20T10:00:00Z" } ] } }

Error codes

Errors return a non-2xx status and a JSON body with success: false and a machine-readable code.

HTTPCodeMeaning
400VALIDATION_ERRORA request parameter is missing or invalid.
401INVALID_AUTHThe API key is missing or invalid.
403FORBIDDENAccount suspended or a limit was reached.
404NOT_FOUNDThe requested resource does not exist.
409IDEMPOTENCY_CONFLICTSame idempotency key reused with a different body.
402INSUFFICIENT_BALANCENot enough account balance to fund the card or top-up. Top up your balance first.
409CARD_NOT_READYThe card is not issued/activated yet. Wait for issue_status: issued before topping up.
429RATE_LIMITToo many requests. Slow down and retry.
502ISSUER_ERRORThe card issuer could not provision the card. A balance-funded charge is refunded automatically; retry later.
500INTERNAL_ERRORUnexpected server error. Retry with backoff.
503UPSTREAM_ERRORA payment or issuing partner is temporarily unavailable.

Rate limits

Each account has a per-minute request limit and a daily card-issuance cap. Limits depend on your plan and can be raised on request.

Request rate
Per-plan req / min
Daily issuance
Per-plan cards / day

Exceeding a limit returns 429 RATE_LIMIT. Need more headroom? Contact us.

IZIPAY Business API · Request access · izipay.me