Overview

What paygate is, and the four things that will bite you if you skip them.

paygate takes USDT payments over an HTTP API and webhooks. Your customer pays from a hosted page; you write no web3 code, hold no keys, and never see a wallet library.

Everything below is the same for every integration, whatever you are billing for.

The shape of it

  1. You create a payment and get back an address and an exact amount per chain.
  2. You send the customer to checkout_url — or draw the checkout in your own app, from a live stream of the same data. See In-app checkout.
  3. The chain is watched. As the transfer lands and confirms, the payment moves through detected → confirming → paid.
  4. You are told, by webhook, at every step.

Four things to know before you integrate

1. paid is not final

A chain reorganisation deeper than the confirmation window moves a paid payment to reversed and emits payment.reversed. If you ship goods on payment.paid, you are accepting that risk knowingly — and you can rehearse it:

curl -X POST https://api.paygatehq.com/v1/test/payments/{id}/reorg \
  -H "Authorization: Bearer sk_test_..." \
  -H "Idempotency-Key: $(uuidgen)" -d '{}'

Wait for settled instead if you cannot absorb a reversal.

2. Webhook delivery is at least once

Every event carries a stable id. Deduplicate on it. A handler that is not idempotent will double-credit an account the first time a delivery is retried after your 200 was lost on the way back.

3. Amounts come as an integer AND a string

amount is micro-units (6 decimal places). amount_decimal is the same value as fixed-point text.

Use the string in any language whose JSON parser produces floats — which is JavaScript, and the reason 25000000 / 1e6 is not reliably 25. See Amounts.

4. USDT has different decimals per chain

Six on Tron, eighteen on BSC. The API always speaks micro-units so you never have to care; the raw on-chain amount is published per route for the wallets that do.

Where to go next