Crypto Payments

Charge in the currency you think in — dollars, euros, naira — and let your customer pay in the coin they hold. ZyraPay gives every payment its own deposit address, watches the chain for it, and settles the funds to you.

How a payment works

  1. 1

    You create a payment

    Tell us the price and which coin the customer will send. We return a pay_address and the exact pay_amount.
  2. 2

    The customer sends funds

    That address belongs to this payment and nothing else, so we always know who paid.
  3. 3

    We watch the chain

    The status moves waiting → confirming → confirmed as blocks stack up on top of the transaction.
  4. 4

    We settle and notify you

    Funds are forwarded to your wallet (or held to your balance), the status reaches finished, and we POST a signed callback to your server.

Create a payment

POST/v1/paymentAPI key
curl https://api.zyrapay.net/v1/payment \
  -H "x-api-key: $ZYRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "price_amount": 25,
    "price_currency": "usd",
    "pay_currency": "usdtbsc",
    "order_id": "ORDER-1042",
    "order_description": "Pro plan — 1 year",
    "ipn_callback_url": "https://yourshop.com/zyrapay/callback"
  }'

Request fields

FieldTypeDescription
price_amountrequirednumberWhat you are charging, in price_currency.
price_currencyrequiredstringWhat you price in. Any supported fiat (usd, eur, gbp, ngn, …) or a crypto ticker.
pay_currencyrequiredstringThe coin the customer will send, e.g. usdtbsc. See Currencies & Networks.
ipn_callback_urlstringWhere we POST status updates. Strongly recommended.
order_idstringYour own reference for this order.
order_descriptionstringShown to the customer on the hosted page.
payout_addressstringForward the settled funds straight to this wallet instead of holding them to your ZyraPay balance.
is_fee_paid_by_userbooleanWhen true, the amount the customer sends is grossed up so you receive the full price after fees.

Response

200 OK
{
  "payment_id": "4830112957",
  "payment_status": "waiting",
  "pay_address": "0x9858effd232b4033e47d90003d41ec34ecaeda94",
  "pay_amount": 24.98,
  "pay_currency": "usdtbsc",
  "price_amount": 25,
  "price_currency": "usd",
  "actually_paid": 0,
  "outcome_amount": 24.855,
  "outcome_currency": "usdtbsc",
  "network": "bsc",
  "network_name": "BNB Smart Chain",
  "confirmations": 0,
  "required_confirmations": 15,
  "order_id": "ORDER-1042",
  "expiration_estimate_date": "2026-08-17T13:00:00.000Z",
  "created_at": "2026-08-17T12:00:00.000Z"
}
Show pay_amount exactly as returned, and make clear which network it must be sent on. A customer who sends a different amount lands in partially_paid; one who sends on the wrong network loses the funds, and no gateway can recover them.

Payment statuses

StatusWhat it means
waitingCreated. Nothing has arrived yet.
confirmingWe saw the transaction. Waiting for enough blocks on top of it.
confirmedEnough confirmations. The funds are irreversible.
sendingWe are moving the funds to their destination.
finishedSettled. This is the status to fulfil the order on.
partially_paidLess arrived than was due. The customer can still top up.
failedSomething went wrong. Funds, if any, are still recoverable.
refundedSent back to the payer.
expiredThe window closed with nothing received.
Fulfil orders on finished, not on confirmed. And treat these as a set you might not have seen before — always handle an unknown status by ignoring it rather than erroring.

Check a payment

GET/v1/payment/{payment_id}API key

Polling works, but a callback is faster and cheaper. Use polling as a backstop, not as your primary signal.

Where the money goes

If you set a payout address for a network — per payment via payout_address, or once in Dashboard → Gateway → Currencies — settled funds are forwarded straight to your own wallet. If you do not, ZyraPay holds the balance for you and you withdraw it when you want.

Forwarding means you hold your own funds from the moment they settle. If that matters to you, set a payout address for every network you accept before going live.

Underpayments and overpayments

Customers mistype amounts. If less arrives than was due, the payment becomes partially_paid and actually_paid tells you how much came in — the customer can send the difference to the same address and it will complete. If more arrives, the payment still finishes and the full amount is settled to you; nothing is left stranded.

Next

Search docs

Search the documentation

Ask the AI assistant