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

Invoice integration guide

This guide walks through a complete invoice integration — from creating an invoice through handling every payment outcome correctly. It covers the on-chain and Binance Pay payment methods and applies equally if you're integrating NFT payments. For NFT-specific setup, see the NFT invoice integration guide alongside this one.

Before you start

Check these before writing any integration code:

  • Supported currency pairs — not every billedCurrency and chargedCurrency combination is valid. Verify yours against the Listing invoice currency pairs endpoint.

  • Amount limits — each billedCurrency has a minimum and maximum. Requests outside the range return HTTP 422. Contact Txn support for the limits per currency.

  • Refund handling — if you want Txn to automatically issue refunds for underpayments, overpayments, or late payments, this is configured at the account level. Contact Txn to set it up before going live. See Invoice refunds for the available options.

  • Hosted page vs. custom UI — decide upfront. The hosted page requires almost no frontend work; a custom UI gives you full control but requires you to handle more edge cases (XRP destination tags, Binance Pay deeplinks, countdown timers).

Step 1: Create the invoice

Send a POST to /api/public/v1/invoices for each payment your end user needs to make. One invoice, one payment attempt.

Key parameters

billedCurrency is the currency you display to the end user — typically the currency in which they hold a balance on your platform (e.g. TRY, USD, CNY). It does not have to be a cryptocurrency.

chargedCurrency and payNetwork define what the end user actually pays in and on which blockchain network. These must be a supported cryptocurrency/token and network combination — see Supported currencies for valid codes.

targetCurrency is the currency that lands in your Txn account after the payment is converted. It must be a tradable fiat currency or cryptocurrencydisplay fiat currencies are not accepted here. If omitted, it defaults to billedCurrency, which must itself be tradable.

This matters in practice: many common billedCurrency values — such as TRY, CNY, and BRL — are display fiat and cannot hold a balance on Txn. If you invoice in one of these currencies, you must supply targetCurrency explicitly (for example, EUR or USD) so Txn knows which account to settle the funds into. Omitting it with a display fiat billedCurrency will return an error.

reference is your internal correlation key. Set it to your order ID, user ID, or any unique value that lets you match the invoice back to a record on your side. It must be unique per invoice. You will see it on every webhook and API response for the invoice's lifetime.

successRedirectUrl and unsuccessRedirectUrl apply only to the hosted page flow. They are the URLs Txn redirects the end user to after a successful payment or after the invoice expires or is cancelled.

What the response gives you

Field
Description

data.attributes.address

The wallet address the end user must send crypto to

data.attributes.amountCharged

The exact crypto amount they need to send

data.attributes.expiresAt

When the exchange rate and invoice expire (20 minutes from creation)

data.attributes.hostedPageUrl

Ready-to-use hosted payment page URL

included[].type(addresses)

Full address entity, including the destination tag for XRP

included[].type(binanceOrders)

Binance Pay order details, when paymentMethods includes binance_pay

Step 2: Present the invoice to the end user

Option A — Hosted page

Redirect the end user to hostedPageUrl. Txn renders the full payment UI: wallet address, QR code, countdown timer, and Binance Pay instructions where applicable. The end user is redirected to your successRedirectUrl or unsuccessRedirectUrl when the invoice reaches a terminal state.

This is the fastest path to production and requires no frontend work beyond the redirect.

Option B — Custom UI

Build your own payment screen using the invoice response data. At minimum, display:

  • The wallet address and a scannable QR code

  • The exact amount to send (amountCharged + chargedCurrency)

  • The payment network by its full name (networkName) — for example, "Tron (TRC20)" rather than the network code ttrx:usdt. Users select the network in their wallet app when initiating a withdrawal; showing the recognisable display name reduces the risk of them choosing the wrong network and sending funds that cannot be recovered.

  • A countdown timer to expiresAt

Binance Pay: if paymentMethods includes binance_pay, the binanceOrders entity in included[] contains:

  • qrcodeLink — a hosted QR code image to display

  • deeplink — opens the Binance app directly on mobile

  • universalUrl — works across both web and mobile browsers

Step 3: Track invoice status

Configure your webhook endpoint in the Txn dashboard. Txn sends a POST request to your endpoint on every status change. The payload is the same shape as the Read invoice response.

Two implementation requirements:

  1. Verify the signature on every incoming webhook before processing it. See Webhooks for signature verification details.

  2. Process webhooks idempotently. The same status transition can be delivered more than once. Use the invoice id and status together as a deduplication key.

See Invoice webhooks for example payloads for each status.

Polling (alternative)

Poll Read invoice by invoice id. A reasonable interval is every 5–10 seconds while the end user is on the payment screen. Reduce the frequency after expiresAt — the invoice can still complete via late payment for up to 7 days, but changes become infrequent.

Status reference

status

Final?

What it means

What to do

pending

No

Awaiting a crypto transaction

No action needed

expired

No

No payment received within 20 minutes

Do not cancel your order — late payment is still possible for 7 days

processing

No

Transaction detected, awaiting confirmations

Optionally show "payment detected" to the end user

on_hold

No

Compliance review in progress

Do not settle — wait for the next status update

completed

Yes

Payment processed and funds credited to your account

Settle based on statusContext — see Step 4

cancelled

Yes

No payment received within 7 days, or payment rejected under refund rules

Check coinDeposits — if non-empty, a refund link may be present

rejected

Yes

Payment declined by Txn compliance

Do not settle

Step 4: Handle payment outcomes

The statusContext and paymentStatus fields give you the full picture of what happened inside a completed or cancelled status. Handle each combination explicitly — do not fall through to a default case.

Full payment, on time

status: completed · statusContext: full · paymentStatus: on_time

Happy path. The end user sent the correct amount within 20 minutes. Proceed to Step 5.

Full payment, late

status: completed · statusContext: full · paymentStatus: late

The end user paid after the invoice expired but within the 7-day monitoring window. Txn processed the payment at the spot exchange rate applicable at the time of receipt. Proceed to credit the end user.

Underpayment

status: completed · statusContext: underpaid

The end user sent less crypto than quoted. Txn applied the spot exchange rate to the amount actually received and settled the result to your account. invoiceTransactions.amountBilled reflects the actual credited amount — it will be less than the original invoice amount. Credit the end user accordingly.

If refund rules are configured for underpayments, Txn may instead reject the payment and issue a refund link. The invoice status will be cancelled in that case — see Cancelled with a refund below.

Overpayment

status: completed · statusContext: overpaid

The end user sent more crypto than quoted. Txn applied the spot exchange rate to the full amount received. invoiceTransactions.amountBilled reflects what was actually processed — it will exceed the original invoice amount. Credit the end user accordingly.

Depending on your refund configuration, Txn may instead process only the original invoice amount and issue a refund link for the excess, or reject the entire payment. See Invoice refunds for the configured behaviour options.

On hold

status: on_hold

Txn's compliance team is reviewing the payment, typically because the source wallet is associated with elevated risk. Do not settle the end user. The invoice will resolve to either completed (payment cleared) or rejected (payment declined). Wait for the next webhook.

Rejected

status: rejected — final

The payment was declined by Txn compliance. Txn returns the funds to the sender. Do not settle the end user.

Cancelled with a refund

status: cancelled · coinDeposits relationship non-empty

A payment was received but rejected under your account's refund rules (underpayment, overpayment, or late payment). The refundLinks relationship will contain a payment link entry. Extract the hostedPageUrl from the corresponding entity in included[] and share it with the end user so they can claim their funds. See Refunds.

No payment received

status: cancelled · statusContext: unpaid · coinDeposits empty

No crypto was ever detected at the invoice address within the 7-day monitoring window. Safe to treat as abandoned — cancel the corresponding order on your side.

Step 5: Credit the end user

When the invoice reaches completed, read invoiceTransactions.amountBilled from the included[] array. This is the amount in billedCurrency that the end user's payment actually resulted in, and it is the value to credit to the end user's balance on your platform.

In a full, on-time payment, invoiceTransactions.amountBilled equals the original invoice amount. In underpayment and overpayment scenarios, Txn applies the spot exchange rate to the crypto actually received, so the value will differ.

For fee reporting: invoiceTransactions.transactionFee and invoiceTransactions.targetTransactionFee give you the fee breakdown in billedCurrency and targetCurrency respectively.

Refunds

When Txn's refund handling is enabled for your account and a qualifying payment comes in (underpaid, overpaid, or late), Txn rejects the payment and creates a refund link instead of crediting your account. The invoice status becomes cancelled and the refundLinks relationship in the API response and webhook payload contains the refund payment link.

To handle a refund in your integration:

  1. Detect status: cancelled with a non-empty refundLinks relationship.

  2. Find the corresponding paymentLinks entity in included[].

  3. Extract its hostedPageUrl.

  4. Deliver that URL to your end user — by email, in-app notification, or however you communicate with them.

The end user visits the URL, enters their wallet address, and Txn sends the crypto back to them directly. The refund link can only be used once. Funds are returned in the same currency and on the same network as the original payment. Network and service fees are deducted from the refund amount — if the refund amount is smaller than the combined fees, Txn cannot process the refund.

See Invoice refunds for a full breakdown of each scenario and the available configuration options.

Subsequent payments to a completed invoice address

After an invoice completes, Txn continues to monitor its receiving address. If the end user sends another crypto transaction to the same address — for example, paying twice by mistake — Txn can automatically credit the incoming funds to your crypto account (for example, your USDT account) rather than leaving them unprocessed.

This behaviour is optional and configured at the account level. Contact Txn support to enable it.

When a subsequent payment is credited, it appears as a coinTransaction in your account's transaction history. The transaction inherits the reference of the original invoice, so your existing reconciliation logic can correlate it back to the originating order using the same reference matching you already apply to invoices. The original invoice is not affected — it remains in its completed state.

Reconciliation

  • Correlate with your records — the reference you set on creation is returned on every invoice response and webhook. Use it to look up the corresponding order or user in your system.

  • Blockchain proofcoinTransactions.txHash (in included[]) is the on-chain transaction hash. Store it and share it with the end user if they need confirmation that the payment was sent.

  • Batch reconciliation — use the List invoices endpoint with the created_at_from and created_at_to parameters to pull all invoices in a given date range.

  • Fee accountinginvoiceTransactions.transactionFee and invoiceTransactions.targetTransactionFee are available for each completed invoice.

Last updated