Skip to main content
Tender generates a unique deposit address for each payment request. Your customer sends the exact crypto amount to that address, Tender detects the on-chain transfer, and marks the transaction complete. No custodial account or key management is required on your side.

How it works

1

Initiate a payment

Call POST /payment/initiate with the fiat amount, the chain and the crypto currency. Tender returns a deposit walletAddress, the all-in crypto amount to collect, and a txId to track the payment.
2

Customer sends crypto

Display the walletAddress and exact amount to your customer. They send from their own wallet — any compatible wallet on that chain works.
3

Tender detects the transfer

Tender checks the address on-chain automatically and sends webhook events as the payment progresses.
4

Validate the payment

Call POST /payment/validate/{id} to check the payment on demand and read its current status.

Prerequisites

Authentication guide

Payment endpoints use Basic (Access ID) authentication — only your x-access-id header is required. See the authentication guide for details on both auth methods.

Pricing: what amount means

amount is a fiat price, not a crypto amount:
  • On POST /payment/initiate, it is in your outlet’s default fiat currency (USD if none is set).
  • On POST /payment/initiate/{currency}, it is in the fiat currency named in the path, such as ngn.
Tender converts it to the chosen cryptocurrency and adds every fee on top (the receive fee, any activation fee, any auto-payout fees and, on Tron, the gasless network service fee). The response’s amount is the all-in crypto total the customer must send. To show the customer that total before creating a payment, call POST /payment/quote/{currency}. Its totalPayable matches what initiation charges.

Step 1 — Initiate a payment

A reference can be used by only one payment at a time. Reusing the reference of a payment that isn’t cancelled returns 409. See Initiate Payment for the full response and error list.

Step 2 — Show payment details to your customer

Display the deposit address, the network and the exact amount from the response.
The walletAddress is unique to this transaction. Never reuse addresses across payments.

Step 3 — Poll for payment status

POST /payment/validate/{id} returns HTTP 202 with the payment once funds have arrived. Until then it returns HTTP 406 with the message Payment Not made yet. A 406 is not a failure: keep polling until your own checkout deadline.
Use webhooks instead of polling for production. Register a webhook and Tender pushes transaction_completed, transaction_partially_paid, transaction_overpayment and the other payment events as they happen. See Webhooks.

Payment status values

completed and overpayment are final. A payment can only be cancelled through the API while it is pending.

Internal transactions

Some payments are settled in more than one step. A payment can be bridged to another chain, or converted as it settles, and each step is its own on-chain transaction. These transactions don’t appear in your payment list, because they belong to a payment you already see. To get them, with hashes and explorer links, call List Payment Internal Transactions with the payment’s txId: Most payments have none and return an empty list.

Unpaid payments

Payments don’t fail. A request with no funds received moves from pending to reserved after about 2 hours, and Tender cancels it automatically once it has been unpaid for at least a day. The automatic cancellation doesn’t send a webhook. If your checkout has its own time limit, cancel the request yourself when it passes with POST /payment/cancel/{id}. Cancelling sends the transaction_cancelled webhook and frees the payment’s reference for reuse.

Partial payments and overpayments

If the customer sends less than the required amount (by $0.10 or more), the payment moves to partial-payment. A smaller shortfall is treated as completed. While a payment is partial-payment:
  • balanceRequired shows what is still owed. The customer can send the rest to the same address.
  • Tender keeps checking for 24 hours from the first partial payment. After that it accepts the partial amount as final: isFulfilled becomes true, fulfilledBy is expiry, and Tender sends the transaction_partial_fulfilled webhook. The status stays partial-payment.
If the customer sends noticeably more than required (about $3 or more over), the payment moves to overpayment.

Error handling