CryptoPayrdocs
Home Dashboard Get API key

API reference

The CryptoPayr API lets you accept cryptocurrency payments, track their status, and pull live market data. It's a plain REST API that returns JSON. The base URL is:

https://cryptopayr.com

Create a payment from your backend, send your customer to the returned hosted checkout, and receive a signed webhook the moment it confirms. No coins ever touch your servers.

On the hosted checkout the customer picks any supported coin and network. Set pay_currency on a payment (or a payment link) to pin a specific coin and skip the picker. Prefer no code? Create a payment link in the dashboard and share the URL.

Authentication

Authenticate write requests with your secret API key as a Bearer token. Find your key in the dashboard. Market-data endpoints (rates, convert) are public.

Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx
Keep your secret key private. Never expose it in client-side code.

OpenAPI & Postman

The whole API — payments, payouts, transfers, refunds, market data and the public exchange endpoints — is described by a machine-readable OpenAPI 3.1 spec. Import it into your client generator, Postman, or an API explorer.

Fees

Crypto processing fees are a percentage that starts at 2% and drops automatically with your volume, plus a flat $0.10 per payment — billed only on successful payments. No setup or monthly fees.

Rolling-month volumeFee
$0 – $9992% + $0.10
$1,000 – $4,9991.5% + $0.10
$5,000+1% + $0.10

Your current rate is shown in the dashboard. By default the merchant absorbs the fee; set buyer_pays_fees: 1 to add it on top of the amount your customer pays.

Create a payment

POST /api/v1/payment/create

Creates a charge and returns a hosted checkout_url to send your customer to.

FieldTypeDescription
amountnumberRequired. Amount in the fiat currency.
currencystringRequired. 3-letter fiat code, e.g. USD.
webhook_urlstringPer-payment endpoint we POST the signed confirmation to. Overrides your account default for this payment; omit to use the default.
success_urlstringRedirect after a successful payment.
cancel_urlstringRedirect if the customer cancels.
pay_currencystringOptional. Pin the pay-in coin (e.g. USDT) to skip the picker.
pay_networkstringOptional. Network for the pinned coin (e.g. TRON).
buyer_pays_fees0 / 1Add the processing fee on top of the amount.
metadatastringYour own reference (≤ 255 chars), echoed back in webhooks.
on_behalf_ofstringPlatforms only. A client's account ID (usr_…) to credit instead of yourself. Requires a platform account.
platform_fee_percentnumberPlatforms only. Commission percent of the order value (0–50). Deducted from the client's net.
platform_fee_fixednumberPlatforms only. Fixed commission in USD on top of the percent (0–10000).

Marketplaces. If your account is a platform account, pass on_behalf_of with a client's account ID (they share their usr_… id with you) to create the charge on their account, authenticated with your API key. Your commission (platform_fee_percent of the order value plus platform_fee_fixed) is deducted from the client's net when the payment completes and credited to your balance — capped at the client's net so it can never go negative. List the Orders you've created with GET /api/v1/transactions?role=platform, and register a platform webhook in your platform settings to receive a signed order.completed event (with the commission_usd) for each one. Ordinary merchants can ignore these fields.

Send an Idempotency-Key header (any unique string, e.g. a UUID) to make retries safe — replaying the same key for 24h returns the original payment instead of creating a duplicate. Replays come back with an Idempotency-Replayed: true header.

curl -X POST https://cryptopayr.com/api/v1/payment/create \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 149.00,
    "currency": "EUR",
    "webhook_url": "https://shop.example/hook",
    "success_url": "https://shop.example/thanks",
    "metadata": "order_4815"
  }'

Response

{
  "status": "success",
  "message": "Payment created",
  "data": {
    "tid": "8f14e45f-ceea-467e-9a36-dcd1f8d7a2b1",
    "status": "CREATED",
    "amount": 149.00,
    "currency": "EUR",
    "checkout_url": "https://cryptopayr.com/payment/8f14e45f-ceea-467e-9a36-dcd1f8d7a2b1"
  }
}

Look up a payment

GET /api/v1/payment/lookup?tid={tid}

Public, read-only status check. Used for reconciliation and by the hosted checkout to detect confirmation.

curl https://cryptopayr.com/api/v1/payment/lookup?tid=8f14e45f-ceea-467e-9a36-dcd1f8d7a2b1

Response

{
  "status": "success",
  "data": {
    "tid": "8f14e45f-ceea-467e-9a36-dcd1f8d7a2b1",
    "status": "COMPLETED",
    "amount": "149.0000",
    "amount_usd": "172.3200",
    "currency": "EUR",
    "created_at": "2026-06-06 12:00:00",
    "expires_at": "2026-06-06T13:00:00+01:00",
    "expires_in": 3214,
    "coin": "USDT",
    "crypto_amount": 172.32,
    "received": 172.32,
    "remaining": 0,
    "partial": 0
  }
}

The coin, crypto_amount, received, remaining and partial fields appear once the customer has selected a coin on the hosted checkout — handy for showing live payment progress. expires_in is the seconds left before the invoice expires.

List transactions

GET /api/v1/transactions

Returns your transactions, newest first, 50 per page. Authenticate with your secret API key.

QueryTypeNotes
pageinteger1-based page number. Default 1.
statusstringOptional filter: CREATED, PENDING, COMPLETED, EXPIRED or CANCELLED.
sortstringdate (default, newest first) or status (grouped by status).
rolestringPlatforms only. merchant (default — your own received payments) or platform (the Orders you created on behalf of clients). The platform listing adds on_behalf_of, platform_fee_percent, platform_fee_fixed and commission_usd (the credited commission, or null until the Order completes) to each row.
curl https://cryptopayr.com/api/v1/transactions?page=1&status=COMPLETED \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"

Response

{
  "status": "success",
  "data": {
    "page": 1,
    "per_page": 50,
    "total": 128,
    "total_pages": 3,
    "has_more": true,
    "data": [
      {
        "tid": "8f14e45f-ceea-467e-9a36-dcd1f8d7a2b1",
        "status": "COMPLETED",
        "amount": 149.00,
        "currency": "EUR",
        "amount_usd": 172.32,
        "buyer_pays_fees": 0,
        "metadata": "order-1024",
        "created_at": "2026-06-06T12:00:00+01:00"
      }
    ]
  }
}

Cancel a payment

POST /api/v1/payment/cancel

Void an unpaid invoice early instead of waiting for it to expire. Body: { "tid": "…" }. Only CREATED/PENDING payments can be cancelled — a COMPLETED one returns 409.

curl -X POST https://cryptopayr.com/api/v1/payment/cancel \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"tid":"8f14e45f-ceea-467e-9a36-dcd1f8d7a2b1"}'

Response

{ "status": "success", "data": { "tid": "8f14…", "status": "CANCELLED" } }

Balance

GET /api/v1/balance

Returns your current wallet balance, all USD-denominated. Authenticate with your secret API key.

curl https://cryptopayr.com/api/v1/balance \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"

Response

{
  "status": "success",
  "data": {
    "currency": "USD",
    "available": 12840.50,
    "pending": 50.00,
    "lifetime_credited": 184210.77
  }
}

available is withdrawable now; pending is reserved for in-flight payouts; lifetime_credited is everything ever credited to you, net of fees.

Account info

GET /api/v1/account

Your own account details — including your public account id (usr_…), which others use to send you internal transfers.

curl https://cryptopayr.com/api/v1/account \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"

Response

{
  "status": "success",
  "data": {
    "account_id": "usr_AbC123…",
    "business_name": "Acme Store",
    "email": "[email protected]",
    "is_activated": true,
    "fee_percent": 2,
    "fixed_fee": 0.10,
    "referral_code": "AbC123",
    "default_webhook": "https://acme.com/cryptopayr",
    "default_success": null,
    "default_cancel": null,
    "created_at": "2026-01-01T00:00:00+00:00"
  }
}

Create a refund

POST /api/v1/refund/create

Refund a completed payment. We email the customer a link to choose where to receive it; funds move once they claim it. Authenticate with your standard API key.

FieldTypeNotes
tidstringRequired. The payment to refund.
amountnumberOptional USD amount; omit for the full remaining refundable amount.
emailstringOptional; defaults to the payment's stored customer email.
reasonstringOptional note shown to the customer.
curl -X POST https://cryptopayr.com/api/v1/refund/create \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"tid":"8f14…","amount":25,"email":"[email protected]"}'

Response

{ "status": "success", "data": { "refund_id": "…", "status": "REQUESTED", "tid": "8f14…", "claim_url": "https://cryptopayr.com/refund/…" } }

List refunds

GET /api/v1/refunds?page={n}&status={s}

Your refunds, newest first, 50 per page. Optional status: REQUESTED, PROCESSING, COMPLETED, REJECTED, CANCELLED. Same {page,per_page,total,total_pages,has_more,data[]} envelope as the other lists.

Webhooks

When a payment is confirmed we POST a JSON event to your webhook_url — the endpoint you set per payment, or your account default from the dashboard settings. This is how you fulfil orders server-side; never rely on the buyer's browser reaching your success_url.

Request we send

POST /your/webhook  HTTP/1.1
Content-Type: application/json
X-CryptoPayr-Signature: 9f86d081884c7d659a2feaa0c55ad015a839f4f8...

{
  "tid": "8f14e45f-ceea-467e-9a36-dcd1f8d7a2b1",
  "status": "COMPLETED",
  "amount": "149.0000",
  "currency": "EUR",
  "metadata": "order_4815",
  "timestamp": 1781049600
}

Payload fields

FieldTypeDescription
tidstringThe transaction id you got from create.
statusstringThe event — see the table below.
amountstringOrder amount in the fiat currency.
currencystring3-letter fiat code.
metadatastringYour own reference, echoed back verbatim.
timestampintegerUnix time the event was sent.
settlementstringconvert (credited as USD) or direct (credited in the coin paid). Present once a payment attempt exists.
settled_assetstringDirect settlement only — the coin your balance was credited in.
settled_networkstringDirect settlement only — the network the deposit arrived on.
received_cryptostringDirect settlement only — the cumulative on-chain amount received, as a decimal string.
refund_idstringREFUNDED only — the refund this event is about. The same id POST /refund/create returned and GET /refunds lists.
refund_amountstringREFUNDED only — the USD amount refunded, as a decimal string. Not the same as amount, which stays the original order total.
refund_currencystringREFUNDED only — always USD, the currency refund_amount is stated in.
refund_settlementstringREFUNDED only — convert (refunded out of your USD balance) or direct (out of your coin balance).
refund_asset / refund_networkstringREFUNDED only — the coin and network the refund was sent on.
refund_asset_amountstringREFUNDED + direct settlement only — the coin amount that left your balance, as a decimal string.
Refunds can be partial, and there can be several against one payment. Every REFUNDED event for a payment repeats the same tid, amount and metadatarefund_id is what makes each one distinguishable, so key your refund bookkeeping on it rather than on tid. Note also that a refund does not change the payment's own status: GET /payment/lookup still reports COMPLETED afterwards. Reconcile against GET /refunds.

Events

statusWhen it fires
COMPLETEDPayment confirmed on-chain (or an in-tolerance underpayment was accepted). Funds are credited to your balance. This is the event to fulfil orders on.
PENDINGSent if you re-send an event while a transaction is still awaiting confirmations (e.g. via the dashboard's Resend webhook).
EXPIRED / CANCELLEDSent if you re-send an event for a transaction that expired or was cancelled. Use it to release a held order.
REFUNDEDA refund against this payment was sent on-chain. Fires automatically when the refund completes — reconcile your records and notify the customer if needed. Carries the refund_* fields above.
A successful payment delivers a single COMPLETED event automatically, and each completed refund a single REFUNDED one. The other statuses share the same signed format and are delivered when an event is re-sent from the dashboard — treat your handler as status-driven and idempotent (key on tid, and on refund_id for refunds) so it stays correct as more automatic events are added.

Testing your handler

Every event above can be delivered to your endpoint from test mode — including REFUNDED, so you never have to issue a live-money refund just to see its shape. Test payments are fully isolated: they never touch your balance, stats or reports. Take your sk_test_… key from Portal → Developers, create a payment with it exactly as you would with your live key, then drive it to the event you want:

curl -X POST https://cryptopayr.com/api/v1/payment/test-complete \
  -H "Authorization: Bearer sk_test_…" \
  -H "Content-Type: application/json" \
  -d '{"tid":"tt_…","status":"REFUNDED","refund_amount":19.99}'

The response echoes the exact webhook_payload that was signed and sent. Pass the same refund_id twice to replay one refund event and prove your handler is idempotent. Test webhooks are signed with your test key and carry "test": true plus an X-CryptoPayr-Test: true header — otherwise the payload is the live shape.

Verifying the signature

Every webhook carries an X-CryptoPayr-Signature header: an HMAC-SHA256 of the raw request body keyed with your secret API key (the same sk_live_… key you authenticate with). Compute the HMAC over the exact bytes you received and compare in constant time. Our official plugins verify the same way.

$body = file_get_contents('php://input');
$sig  = $_SERVER['HTTP_X_CRYPTOPAYR_SIGNATURE'] ?? '';

$expected = hash_hmac('sha256', $body, $API_KEY);   // your sk_live_… key
if (!hash_equals($expected, $sig)) {
    http_response_code(400);
    exit;                                            // reject — not from CryptoPayr
}

$event = json_decode($body, true);
if ($event['status'] === 'COMPLETED') {
    // mark order $event['metadata'] as paid (idempotent on $event['tid'])
}
http_response_code(200);
Always return 200 OK once you've stored the event. Delivery is a single attempt with a 15-second timeout and is not retried automatically — every attempt is logged, and a failed one can be re-sent by hand from the transaction page in your dashboard. So treat the webhook as a fast notification, not a guarantee: reconcile anything that matters against GET /payment/lookup and GET /refunds. Rotating your API key in the dashboard also rotates the webhook signing key.

Send a buyer receipt

POST /api/v1/payment/receipt

A customer email is never required to take a payment. Call this after a completed payment to email the buyer a branded receipt — it's what the hosted checkout uses when a buyer opts in. The transaction must already be COMPLETED.

FieldTypeDescription
tidstringRequired. The completed transaction id.
emailstringRequired. Where to send the receipt.
curl -X POST https://cryptopayr.com/api/v1/payment/receipt \
  -H "Content-Type: application/json" \
  -d '{ "tid": "8f14e45f-ceea-467e-9a36-dcd1f8d7a2b1", "email": "[email protected]" }'

Response

{ "status": "success", "message": "Receipt sent", "data": { "tid": "8f14e45f-..." } }

Exchange rates

GET /api/v1/rates — every tracked coin's USD price.
GET /api/v1/rates/{COIN} — one coin.

curl https://cryptopayr.com/api/v1/rates/BTC

Response

{
  "status": "success",
  "data": { "currency": "BTC", "usd_rate": 68000, "base": "USD" }
}

Currency conversion

GET /api/v1/convert?from={A}&to={B}&amount={n}

Convert between any supported fiat/crypto pair, routed through USD. Crypto results carry 8 decimals, fiat 2.

curl "https://cryptopayr.com/api/v1/convert?from=USD&to=BTC&amount=100"

Response

{
  "status": "success",
  "data": {
    "from": "USD", "to": "BTC", "amount": 100,
    "result": 0.00147058, "rate": 0.0000147058
  }
}

Underpayments & expiry

Invoices expire 1 hour after creation. The hosted checkout shows a live countdown.

If a buyer sends less than the invoiced amount, the checkout shows the exact shortfall so they can top up to the same address. Merchants can opt to accept underpayments in the dashboard — when enabled, a short payment is marked complete and the normal webhook fires.

A customer email is never required to take a payment. After a successful payment the buyer can optionally enter their email to receive a receipt.

Popup checkout (JavaScript SDK)

Take a payment without leaving your page. Create the payment server-side (so your secret key never touches the browser), hand the returned tid to cryptopayr.js, and it opens the hosted checkout in a popup and calls you back when it completes or closes.

<script src="https://cryptopayr.com/assets/js/cryptopayr.js"></script>

The transaction id is a public, unguessable reference — it's safe to expose in the browser. Your secret API key is not; keep POST /payment/create on your backend.

Open the checkout

// 1) Your backend created the payment and returned its tid.
// 2) Open the popup for it:
CryptoPayr.open({
  tid: 'TRANSACTION_ID_FROM_YOUR_BACKEND',
  onSuccess: function (payment) {
    // Confirmed. payment = the public lookup payload (tid, status, amount, …).
    console.log('Paid!', payment);
  },
  onClose: function (info) {
    // The popup flow ended. info.status is COMPLETED | EXPIRED | CANCELLED | ABANDONED.
    if (!info.completed) console.log('Closed without paying');
  },
  onError: function (err) {
    // err.reason === 'popup_blocked' (use err.checkoutUrl as a fallback link)
    // or 'invalid_tid'.
  }
});

Or bind a button — no JS

Any element with data-cryptopayr-tid opens the popup on click and dispatches DOM events you can listen to. Add data-cryptopayr-redirect to send the buyer somewhere on success.

<button data-cryptopayr-tid="TRANSACTION_ID"
        data-cryptopayr-redirect="/thank-you">
  Pay with crypto
</button>

<script>
  document.addEventListener('cryptopayr:success', function (e) {
    console.log('Paid', e.detail);   // e.detail is the payment
  });
</script>

Callbacks

CallbackFires
onSuccess(payment)Payment confirmed (COMPLETED). payment is the public lookup payload.
onClose(info)The popup flow ended — once, after onSuccess on a paid flow. info.status is COMPLETED, EXPIRED, CANCELLED or ABANDONED; info.completed is true only when paid. Use it to re-enable your UI.
onPending(payment)Optional. Once, when funds are first detected.
onError(err)The popup was blocked (err.reason === 'popup_blocked', with err.checkoutUrl as a fallback) or the tid was missing.

CryptoPayr.open() also accepts closeOnSuccess (default true), pollInterval (ms, default 2500) and width / height. It returns a handle with a close() method and the resolved checkoutUrl.

The SDK is a convenience layer over the hosted checkout and the public lookup endpoint. Your signed webhook remains the source of truth for fulfilment — always treat the webhook (not a browser callback) as the authority before releasing goods.

Pay with balance

Buyers who have their own CryptoPayr account can pay you instantly from their wallet balance instead of sending coins. When a signed-in buyer opens your checkout and their available balance covers the order, a “Pay with Balance” button appears; a confirmation page settles it off-chain in one click.

Nothing to integrate — it's automatic on the hosted checkout, including inside the popup SDK. A balance payment completes through the exact same flow as a coin payment: you're credited the order value net of the normal processing fee and receive the same signed COMPLETED webhook. Internally the pay-in is recorded as USDC on Polygon (the stablecoin form of the USD balance).

Buyers only see the button when they're logged in and hold enough balance, and a buyer can never pay their own order from balance. If a coin is pinned with pay_currency, the option is still offered from the deposit page.

Request a withdrawal

Programmatically withdraw your available balance to a crypto address. Because this endpoint moves funds out, it is authenticated with a separate withdrawal key — not your standard API key.

Generate the withdrawal key under Developers → Withdrawal key. For security only a hash is stored, so the key (wk_live_…) is shown once at generation. Regenerating invalidates the previous key immediately.

POST /api/v1/payout/create

Authenticate with the withdrawal key as a Bearer token:

Authorization: Bearer wk_live_xxxxxxxxxxxxxxxxxxxxxxxx
FieldTypeNotes
amountnumberRequired. USD amount to withdraw from your available balance.
currencystringCoin to receive, e.g. USDT. Default USDT.
networkstringNetwork, e.g. TRON. Default TRON.
addressstringDestination wallet address. Required unless address_id is given.
address_idintegerOptional. Use a saved address book entry — its address, currency and network are used.
curl -X POST https://cryptopayr.com/api/v1/payout/create \ -H "Authorization: Bearer wk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{"amount":50,"currency":"USDT","network":"TRON","address":"T..."}'

Response

{ "status": "success", "message": "Payout requested", "data": { "payout_id": 42, "status": "PROCESSING", "amount": 50, "platform_fee": 0.5, "receive_estimate": 48.4, "currency": "USDT", "network": "TRON", "address": "T..." } }

Payouts are dispatched immediately — there is no manual approval step. A successful call returns PROCESSING; on-chain confirmation moves it to COMPLETED. Your balance is checked atomically, so a payout can never exceed your available balance.

If the call fails it returns HTTP 502 with: "Something possible went wrong, your payout might have been sent, if not contact us [email protected]". In this case the withdrawal may already have been sent and your balance is not credited back — do not blindly retry; contact support to reconcile. Always send an Idempotency-Key so a retried request replays the original result instead of dispatching a second payout.

If a withdrawal whitelist is enabled on your account, the address must be one of your saved addresses.

List payouts

GET /api/v1/payouts

Returns your payouts, newest first, 50 per page. This is a read endpoint — authenticate with your standard API key (not the withdrawal key).

QueryTypeNotes
pageinteger1-based page number. Default 1.
statusstringOptional filter: PENDING, PROCESSING, COMPLETED or REJECTED.
curl https://cryptopayr.com/api/v1/payouts?page=1 \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"

Response

{
  "status": "success",
  "data": {
    "page": 1,
    "per_page": 50,
    "total": 7,
    "total_pages": 1,
    "has_more": false,
    "data": [
      {
        "payout_id": 42,
        "status": "COMPLETED",
        "amount": 50.00,
        "platform_fee": 0.50,
        "receive_estimate": 48.40,
        "currency": "USDT",
        "network": "TRON",
        "address": "T...",
        "tx_hash": "9d2c…",
        "created_at": "2026-06-06T12:00:00+01:00"
      }
    ]
  }
}

Get a payout

GET /api/v1/payout/lookup?id={payout_id}

Returns a single payout you own. Authenticate with your standard API key. A payout id that isn't yours returns 404.

curl https://cryptopayr.com/api/v1/payout/lookup?id=42 \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"

Response

{
  "status": "success",
  "data": {
    "payout_id": 42,
    "status": "COMPLETED",
    "amount": 50.00,
    "platform_fee": 0.50,
    "receive_estimate": 48.40,
    "currency": "USDT",
    "network": "TRON",
    "address": "T...",
    "tx_hash": "9d2c…",
    "created_at": "2026-06-06T12:00:00+01:00"
  }
}

The tx_hash is the processor/on-chain reference once the payout has been dispatched (null until then).

Transfer to an account

Move balance to another CryptoPayr account instantly and for free — an internal book transfer, nothing touches the chain. Because it moves funds out of your balance, it uses your withdrawal key (wk_live_…), not your standard API key.

POST /api/v1/transfer/create

Authorization: Bearer wk_live_xxxxxxxxxxxxxxxxxxxxxxxx
FieldTypeNotes
recipientstringRequired. The destination account's public id, e.g. usr_AbC123… (aliases: to, user_id).
amountnumberRequired. USD amount to send from your available balance.
notestringOptional memo (≤255 chars).
curl -X POST https://cryptopayr.com/api/v1/transfer/create \ -H "Authorization: Bearer wk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{"recipient":"usr_AbC123","amount":25,"note":"invoice 1024"}'

Response

{ "status": "success", "message": "Transfer complete", "data": { "transfer_id": "txf_AbC123…", "status": "COMPLETED", "amount": 25, "currency": "USD", "recipient": "usr_AbC123", "recipient_name": "Acme Store", "note": "invoice 1024", "created_at": "2026-06-08T12:00:00+01:00" } }

The transfer is atomic — your balance is debited and the recipient credited in one step, or nothing happens. Insufficient balance returns 422; an unknown recipient returns 404; sending to your own account is rejected. Send an Idempotency-Key header so a retried request replays the original result instead of sending twice.

List transfers

GET /api/v1/transfers?page={n}&direction={in|out}

Your internal transfers (sent and received), newest first, 50 per page. Each row has a direction (in/out) and the counterparty account id. Authenticate with your standard API key.

Get a transfer

GET /api/v1/transfer/lookup?id={txf_…}

One transfer you're a party to (by its txf_ id). Returns 404 if you're neither sender nor recipient.

Estimate a payout

GET /api/v1/payout/estimate?amount={n}¤cy={c}&network={n}

Preview the platform fee, network fee and net "you receive" amount before sending a withdrawal — nothing is created. currency defaults USDT, network defaults TRON.

{ "status": "success", "data": { "amount": 50, "platform_fee": 0.5, "network_fee": 1.1, "receive_estimate": 48.4, "currency": "USDT", "network": "TRON" } }

Payout addresses

GET /api/v1/payout-addresses — list saved addresses.
POST /api/v1/payout-addresses — add one (currency, network, address, optional label, make_default).
DELETE /api/v1/payout-addresses?id={id} — remove one.

Your saved address book — the same one the withdrawal endpoint can target with address_id, and that the optional withdrawal whitelist enforces.

Payment statuses

StatusMeaning
CREATEDPayment created, awaiting the customer.
PENDINGFunds detected, awaiting confirmations.
COMPLETEDPaid and confirmed. Webhook fired.
EXPIREDCheckout link expired before payment.
CANCELLEDCancelled by the customer or merchant.

Errors

Errors use standard HTTP status codes and a JSON body:

{ "status": "failed", "error": "Invalid API key", "timestamp": 1781049600 }
CodeMeaning
401Missing or invalid API key.
404Resource or currency not found.
422Missing or invalid parameters.
429Rate limit exceeded — see below.
500Something went wrong on our side.

Rate limits

Every API response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (unix time). When you exceed a window we return 429 with a Retry-After header.

EndpointLimit
POST /payment/create120 / min per merchant
GET /rates, /convert, /payment/lookup120 / min per IP
POST /payment/receipt20 / min per IP

Need a hand? Email [email protected].