NowgateDocs

Payments

How a payment moves from waiting to finished, and what happens when customers pay too little, too much or too late.

On this page

A payment is one request to be paid: a network, an asset, an amount and a deposit address that belongs to this payment alone. Create one per order, with your order's ID as its idempotency key:

const payment = await nowgate.payments.create(
  { network: "tron", asset: "USDT", amount: "25.00", order_id: "1042" },
  { idempotencyKey: orderKey },
);

Statuses#

StatusMeaning
waitingCreated; nothing seen on-chain yet.
confirmingA deposit is on-chain but not final yet. If a reorganization drops it, the payment returns to waiting.
partially_paidLess than the amount has been confirmed. The customer can top up until the payment expires.
finishedThe amount is confirmed and your balance is credited. Overpayments are credited in full and flagged.
expiredNothing arrived before the payment expired.
failedIt can't be settled automatically, for example because only the wrong asset arrived. Nowgate reviews it.
refundedRefunds returned everything it credited to the payer.

Nowgate recomputes the status from what is on-chain every time something changes, so it never drifts from the facts. Each change sends a webhook.

Amounts#

Amounts are decimal strings in the asset's own units: "49.90" USDT, "0.0015" BTC. They are never JSON numbers, and amounts with more decimal places than the asset has are rejected, not rounded. Nowgate returns amounts in canonical form, so "49.90" comes back as "49.9".

Every asset has a minimum payment so network fees can't eat it. The network list and GET /v1/assets show each one.

FieldMeaning
amountWhat you asked for.
amount_pendingSeen on-chain, not final yet.
amount_receivedConfirmed so far.
amount_creditedCredited to your balance, before fees.
amount_refundedReturned to the payer by finished refunds.
refund_pendingWhat refunds under way will return.
feeNowgate's fee on the credited amount.

Prices in a currency#

Give price_amount and price_currency (USD or EUR) instead of amount, and Nowgate converts the price at its newest rate when it creates the payment, with quote showing the rate. How long the amount holds, markups, who pays the fee, and the rates, estimates and minimums behind it are in Prices and rates.

A payment link is a reusable checkout page that never expires, for a product, a ticket or donations; each attempt on it is an ordinary payment with payment_link set. See Payment links.

Expiry#

A payment expires after expires_in seconds (900 to 86,400; your account's default, usually an hour, if you leave it out). A deposit counts as on time if Nowgate saw it before expires_at; block timestamps are never used, because miners control them. A payment whose on-time deposit is still confirming at expiry waits for it.

Underpayments#

If the customer sends less than the amount, the payment becomes partially_paid and they can top up until it expires. At expiry, whatever arrived is credited and the payment stays partially_paid. Decide yourself whether to deliver, refund or ask for the rest.

Overpayments#

If more arrives than the amount, the payment finishes, the whole amount received is credited, and overpaid is true.

Late payments#

Funds that arrive after a payment expired are still yours: the payment reopens, the funds are credited, and late becomes true. Nowgate never ignores customer funds.

Confirmations and reorganizations#

Nowgate credits a deposit only when its network's rule says it is final. Bitcoin waits for more confirmations as amounts grow. Base credits at its safe head, once the block's data is posted to Ethereum, and the other networks wait for their finalized block. The tier comes from the larger of the deposit and the payment amount, so splitting a payment into small transfers can't lower it.

If a reorganization drops a deposit that was already credited, the credit is reversed, reversed becomes true, and you get a payment.reversed event.

Testing in the sandbox#

The sandbox (sandbox-api.nowgate.io) behaves as live does, with one addition: you can make up what a payer does, with POST /v1/sandbox/payments/{id}/simulate, and test every case without testnet coins.

actionWhat happens
paya deposit of exactly what is due
underpaya deposit short by amount, or by half: partially_paid
overpaya deposit over by amount, or by half: finished and overpaid
repeatanother deposit after the payment finished
wrong_assetanother asset of the network to the payment's address, which goes to review
latethe payment expires now, then what was due arrives: late
expirethe payment expires now

A simulated deposit is pending at first, as one in the mempool is, and settles about ten seconds later. From then on it is processed like any deposit, with the same statuses, credits and webhooks. Simulated money stays in the sandbox's books and is never swept. In live the route doesn't exist. See the sandbox for payouts and refunds there too.

Retries and idempotency#

Every POST needs an Idempotency-Key header. Sending the same request with the same key returns the original response, with Idempotent-Replayed: true, instead of creating a second payment. The same key with a different request is refused with idempotency_key_reused. Failed requests are not stored, so you can retry them with the same key. See Idempotency and retries for what the SDKs retry, and when.

Listing payments#

const walked: string[] = [];
let page = await nowgate.payments.list({ limit: 2 });
walked.push(...page.data.map((p) => p.id));
while (page.has_more) {
  page = await nowgate.payments.list({ limit: 2, starting_after: page.data.at(-1)?.id });
  walked.push(...page.data.map((p) => p.id));
}

GET /v1/payments returns payments newest first, 20 per page by default and up to 100. Filter by status or order_id, and page with starting_after (older) or ending_before (newer) set to a payment ID from the previous page. has_more says whether there is another page. See Pagination.