tomant.pay
TOMANT / DEVELOPERS

Connect payments to orders.

Create invoices from your application. Track settlement with the API and signed webhooks.

1. Create an invoice

The recipient and requested amount are immutable after creation. Store the returned invoice ID, management key, webhook signing secret and payment URL on your server. The management key is returned once.

curl -X POST https://pay.tomant.ir/api/v1/invoices \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: ORDER-1042' \
  -d '{
    "recipient": "0xYOUR_BNB_RECEIVING_WALLET",
    "amount": "250000.0",
    "title": "Design services",
    "reference": "ORDER-1042",
    "expiresInHours": 24,
    "webhookUrl": "https://your-store.com/tomant/webhook"
  }'

An Idempotency-Key prevents a retry from creating another invoice for the same receiving wallet. Reusing it with different details returns HTTP 409. The replay response does not expose the original private management key.

2. Send the payment URL

Send only paymentUrl to the customer. Keep managementUrl and managementKey private. Each link represents one invoice; create a new invoice for each customer order.

GET https://pay.tomant.ir/api/v1/invoices/inv_…

Public status includes the receiving address, requested and settled amounts, transaction receipts, and status. Private payer notes, webhook settings and delivery logs require:

Authorization: Bearer YOUR_INVOICE_MANAGEMENT_KEY
openAwaiting payment
partialConfirmed TOMANT is below the requested amount
paidFull TOMANT amount confirmed with 12 BNB Chain confirmations
paid_lateFull amount settled after the invoice expired; review before fulfilment
expired / partial_expiredNo new checkout; payments already sent continue to be reconciled
cancelledNo new checkout; already-sent payments can still be recorded

3. Verify payment notifications

Webhooks send invoice.partially_paid and invoice.paid. The payload has id, type, createdAt and data (the invoice). The signature is HMAC-SHA256 of timestamp + '.' + rawBody, signed with that invoice’s webhookSecret.

import { createHmac, timingSafeEqual } from 'node:crypto';

// rawBody must be the ORIGINAL request body, not reserialized JSON.
const timestamp = req.headers['x-tomant-timestamp'];
const supplied = req.headers['x-tomant-signature'] || '';
if (!/^\d+$/.test(timestamp || '') ||
    Math.abs(Date.now()/1000 - Number(timestamp)) > 300) {
  throw new Error('Expired webhook');
}
const expected = 'v1=' + createHmac('sha256', signingSecret)
  .update(timestamp + '.' + rawBody).digest('hex');
const a = Buffer.from(expected), b = Buffer.from(supplied);
if (a.length !== b.length || !timingSafeEqual(a, b)) {
  throw new Error('Invalid signature');
}
const event = JSON.parse(rawBody);
// Deduplicate event.id before changing an order.
// Fulfil only on invoice.paid after checking your stored invoice,
// recipient, reference, token, chainId, and full amount.
// Acknowledge durable processing with HTTP 2xx.

Delivery is at least once. Deduplicate by event ID. Failed delivery is retried up to 10 times with increasing delays (maximum delay 6 hours); undelivered events can be retried from the private invoice dashboard. Notifications require a public HTTPS endpoint; redirects are not followed.

Fetch notification history with GET /api/v1/invoices/:id/events and your invoice management key. Change an endpoint with PATCH /api/v1/invoices/:id and {"webhookUrl":"https://…"}.

4. Understand settlement

Direct transfers created by this checkout include an invoice-specific reference in their transaction data. In this pilot, Rango converts assets into the buyer’s own BNB Chain wallet; the buyer then confirms an exact TOMANT payment to the invoice recipient. Conversion success alone never marks a bill paid. Confirmed TOMANT transfer logs on BNB Chain determine the settled amount, and the same transfer log cannot be used on two invoices. Server-proxied merchant routing can be used when Rango server access is available.

Amounts in human-readable fields are decimal strings. amountUnits, receivedUnits and remainingUnits use TOMANT’s 18 on-chain decimals. Invoice amounts support one decimal place. Fees are additional and shown before signing.

Rango uses the configured API key and requires a live executable route into TOMANT. Supported chains do not guarantee every token pair or amount. Cross-chain exact-input conversions can deliver a small excess to the recipient or stop in an intermediate asset if a later step fails. Partial settlement remains unpaid until the full invoice amount arrives. Fiat and bank card payments require a separate on-ramp and are not enabled.
Create a payment link