Quickstart
Create a payment, show its address, and handle the webhook when it is paid.
On this page
Create a payment#
Use an SDK or plain HTTP. With an SDK, make a client with your API key:
const nowgate = new Nowgate({ apiKey: env("NOWGATE_API_KEY"), baseUrl, fetch: counted });client = Nowgate(api_key=env("NOWGATE_API_KEY"), base_url=base_url, transport=counted)$nowgate = new Client(['api_key' => env('NOWGATE_API_KEY'), 'base_url' => $baseUrl, 'transport' => $counted]);Then send the network, the asset and the amount, with an idempotency key so a retry can never create a second payment. Your order ID makes a good key.
const payment = await nowgate.payments.create(
{ network: "tron", asset: "USDT", amount: "25.00", order_id: "1042" },
{ idempotencyKey: orderKey },
);payment = client.payments.create(
network="tron",
asset="USDT",
amount="25.00",
order_id="1042",
idempotency_key=order_key,
)$payment = $nowgate->payments->create(
['network' => 'tron', 'asset' => 'USDT', 'amount' => '25.00', 'order_id' => '1042'],
['idempotency_key' => $orderKey],
);curl https://api.nowgate.io/v1/payments \
-H "Authorization: Bearer $NOWGATE_API_KEY" \
-H "Idempotency-Key: order-1042" \
-H "Content-Type: application/json" \
-d '{"network": "tron", "asset": "USDT", "amount": "49.90", "order_id": "1042"}'The response is the new payment, with status waiting:
{
"id": "pay_01jc3x6k2tf8yq0b5n2c7m9d4v",
"object": "payment",
"status": "waiting",
"network": "tron",
"asset": "USDT",
"amount": "49.9",
"amount_received": "0",
"amount_pending": "0",
"amount_credited": "0",
"fee": "0",
"deposit": { "address": "TN3W4H6rK5ZsKxVbqh8ZpXhVv2dm3kGaQ1" },
"late": false,
"overpaid": false,
"reversed": false,
"order_id": "1042",
"metadata": {},
"expires_at": "2026-11-05T13:00:00Z",
"created_at": "2026-11-05T12:00:00Z",
"updated_at": "2026-11-05T12:00:00Z",
"version": 1
}Show the deposit address#
Show your customer deposit.address, the exact amount and asset, and the network, and when the
payment expires (expires_at, an hour by default). On Stellar, also show deposit.memo: deposits
without it can't be matched.
Or send them to the payment's checkout_url: a hosted page with all of that, a QR code their
wallet can scan, and the payment's live status, in their language.
Receive the webhook#
As the payment changes, Nowgate POSTs events to your endpoint: payment.confirming when the deposit
is seen, then payment.finished when it is final and credited. Verify each one over the raw body
before trusting it. The SDKs verify it for you; without one, use a tested function from the
webhooks guide:
const chunks: Buffer[] = [];
for await (const chunk of request) chunks.push(chunk as Buffer);
const body = Buffer.concat(chunks); // the raw body, exactly as received
const signature = request.headers["nowgate-signature"];
const event = await Webhooks.constructEvent(body, signature, secret);body = self.rfile.read(int(self.headers["Content-Length"])) # the raw body, exactly as received
signature = self.headers["Nowgate-Signature"]
try:
event = Webhook.construct_event(body, signature, secret)
except SignatureVerificationError:
self.send_response(400)
self.end_headers()
return$payload = (string) file_get_contents('php://input'); // the raw body, exactly as received
$header = $_SERVER['HTTP_NOWGATE_SIGNATURE'] ?? null;
try {
$event = Webhook::constructEvent($payload, is_string($header) ? $header : null, $secret);
} catch (SignatureVerificationException $e) {
http_response_code(400);
return;
}Check before you deliver#
A webhook tells you something changed. Before you ship goods, fetch the payment and check its status. In the sandbox you can play the payer to see it happen:
const finished = await until("the payment to finish", async () => {
const current = await nowgate.payments.retrieve(paid.id);
assert.ok(!["expired", "failed"].includes(current.status), current.status);
return current.status === "finished" ? current : undefined;
});def finished() -> Optional[Payment]:
current = client.payments.retrieve(paid["id"])
check(current["status"] not in ("expired", "failed"), current["status"])
return current if current["status"] == "finished" else None
payment = until("the payment to finish", finished)$payment = until('the payment to finish', static function () use ($nowgate, $paid): ?array {
$current = $nowgate->payments->retrieve($paid['id']);
check(!in_array($current['status'], ['expired', 'failed'], true), $current['status']);
return $current['status'] === 'finished' ? $current : null;
});curl https://api.nowgate.io/v1/payments/pay_01jc3x6k2tf8yq0b5n2c7m9d4v \
-H "Authorization: Bearer $NOWGATE_API_KEY"Deliver when status is finished. A payment that received less than its amount is
partially_paid instead: see underpayments.