Receive real-time notifications about transfer events
TON Pay uses webhooks to notify your application in real-time about transfer events. When a payment is completed, TON Pay sends an HTTP POST request to your configured webhook URL with event details.
When a transfer is completed on the blockchain, TON Pay automatically sends a webhook notification to your configured endpoint. The transfer may be successful or failed - check the status field in the payload:
1
Event occurs
A transfer is completed on the blockchain and indexed by TON Pay.
2
Webhook triggered
TON Pay generates a webhook payload and signs it with your API key using
HMAC-SHA256.
3
HTTP POST sent
TON Pay sends a POST request to your webhook URL with the signed payload.
The request includes an X-TonPay-Signature header for verification.
4
Your endpoint responds
Your server receives the webhook, verifies the signature, and processes the event.
Return a 2xx status code to acknowledge receipt.
Important: Webhooks are sent from the TON Pay backend. Ensure your webhook
URL is publicly accessible and can receive POST requests.
Every webhook request includes an X-TonPay-Signature header containing an HMAC-SHA256 signature. You must verify this signature to ensure the request came from TON Pay.
Critical: Never skip signature verification in production. Unverified
webhooks could be forged by malicious actors attempting to manipulate your
payment flow.
Copy
import { verifySignature, type WebhookPayload } from "@ton-pay/api";app.post("/webhook", (req, res) => { const signature = req.headers["x-tonpay-signature"]; if (!verifySignature(req.body, signature, YOUR_API_SECRET)) { return res.status(401).json({ error: "Invalid signature" }); } const webhookData: WebhookPayload = req.body; // Process the webhook... res.status(200).json({ received: true });});
Where to find your API Secret
Your webhook API secret is available in the Merchant Dashboard β
Developer β Webhooks section. Keep it secure and never expose it in
client-side code.
import { type WebhookPayload, type WebhookEventType, type TransferCompletedWebhookPayload, type TransferRefundedWebhookPayload, // Coming Soon} from "@ton-pay/api";// Event types: "transfer.completed" | "transfer.refunded" (Coming Soon)type WebhookEventType = "transfer.completed" | "transfer.refunded";// Union type for all webhook payloadstype WebhookPayload = | TransferCompletedWebhookPayload | TransferRefundedWebhookPayload; // Coming Soon - data structure to be defined
interface TransferCompletedWebhookPayload { event: "transfer.completed"; timestamp: string; data: CompletedTonPayTransferInfo; // See full type definition in API Reference}
All webhook types are available in @ton-pay/api package. Import
WebhookPayload for type safety in your webhook handlers.
Event type. Currently only transfer.completed is supported. Note:transfer.completed means the transfer processing is finished - it may be
successful or failed. Always check the status field in the data to determine
the actual result.
Coming Soon: Additional event transfer.refunded will be available in
future updates.
Check webhook URL in Merchant Dashboard is correct and accessible
Verify endpoint is publicly accessible and not blocked by firewall
Test using Dashboard test feature to send sample webhook
Check webhook attempt logs in the Merchant Dashboard
Ensure endpoint returns 2xx status for valid requests
Verify no request timeout (endpoint must respond within 10 seconds)
Signature verification fails
Get API key from Merchant Dashboard β Developer β API tab - Ensure
payload is raw JSON string when computing HMAC - Donβt modify the request
body before verification - Check header name is exactly
x-tonpay-signature (lowercase) - Verify HMAC algorithm is SHA-256 -
Check signature format starts with sha256=
Amount or asset mismatch
This is a security-critical error. Possible causes: - Wrong order looked
up - verify reference matching logic - Price changed - ensure prices are
locked at order creation - Currency confusion - verify youβre comparing
same currency - Potential attack - log and alert security team Never
fulfill orders with mismatched amounts or assets!
Duplicate webhook processing
Expected behavior - webhooks can be delivered multiple times
Implement idempotency using reference field
Use database transactions to prevent race conditions
Check order status before processing
Copy
if (order.status === 'completed') { return; // Already processed}
Timeout errors
Respond within 10 seconds to avoid timeout
Process webhooks asynchronously after quick validation