Paysell
SolutionsPricingDocsBlog
登录创建账户
guides

Accept USDT on TON in 5 minutes

A step-by-step guide to creating a store, generating an API key, creating an invoice with curl, and confirming payment through a webhook.

Published
2026年8月27日
Reading time
4 min read
Updated
2026年9月12日
On this page
  • Step 1: Create a store
  • Step 2: Create an API key
  • Step 3: Create an invoice with curl
  • Step 4: Open paymenturl
  • Step 5: Receive the webhook
  • Step 6: Mark the order paid
On this page
  • Step 1: Create a store
  • Step 2: Create an API key
  • Step 3: Create an invoice with curl
  • Step 4: Open paymenturl
  • Step 5: Receive the webhook
  • Step 6: Mark the order paid
guidesdevelopers

This guide takes you from a fresh Paysell account to a working integration: a store, an API key, an invoice created with curl, a buyer paying through the hosted checkout, and a webhook that marks the order paid in your system.

Step 1: Create a store#

Register and create a store from the cabinet. A store is the unit that holds your API keys, invoices, and balance — most merchants only need one, but you can create more if you sell under multiple brands.

Your store can accept payments immediately. A background review runs alongside normal operation, but it only gates withdrawals — not incoming payments — so you can start testing right away.

Note: Your key is live from minute one — there is no separate test environment, and that saves time: you exercise the same path your real orders will take. Test with small real amounts — a fraction of a TON is enough to see the full flow.

Step 2: Create an API key#

From the store settings, generate an API key. It's shown to you exactly once, so copy it into your secrets manager or .env file immediately — Paysell can't show it to you again. Keys look like sk_live_... and go in the Authorization header as a bearer token.

Step 3: Create an invoice with curl#

Every payment starts as an invoice. Here's a complete example for a 25 USDT charge:

curl -X POST https://paysell.me/api/merchant/v1/invoices \
  -H "Authorization: Bearer sk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "asset": "USDT_TON",
    "amount": "25",
    "order_id": "order-1042"
  }'

Note that amount is a decimal string, not a number — this avoids floating-point rounding issues. order_id is your own identifier; Paysell doesn't require any particular format, just uniqueness that's meaningful to you.

The response looks like this:

{
  "invoice_id": "inv_8f3ka92ldk",
  "payment_url": "https://paysell.me/pay/inv_8f3ka92ldk",
  "address": "UQCabcdefghijklmnopqrstuvwxyz0123456789ABCD",
  "asset": "USDT_TON",
  "amount": "25",
  "amount_minor": 25000000,
  "status": "pending",
  "expires_at": "2026-08-27T11:00:00Z"
}

amount_minor is the amount in minimal units — USDT uses 6 decimals, so 25 USDT is 25000000. TON uses 9 decimals. The invoice expires 2 hours after creation by default (configurable from 1 minute to 24 hours); you can shorten or extend that with a ttl_minutes parameter.

Step 4: Open payment_url#

Send the buyer to payment_url — a hosted page at /pay/{invoice_id} — or redirect them there right after checkout. The page shows a QR code and a deep link that opens Tonkeeper, MyTonWallet, or another TON wallet with the amount and address pre-filled, plus a countdown until the invoice expires.

If the buyer sends less than the invoice amount, the invoice moves to underpaid and stays open for another 24 hours so they can top it up. If they send more, the full amount is credited to you and the invoice is marked overpaid. If they send the wrong asset entirely, it's still credited to your balance, but the original invoice stays open.

Step 5: Receive the webhook#

Once the payment is included in the TON masterchain plus three blocks and cross-checked against a second data source — about a minute after the buyer pays — Paysell sends a payment.credited webhook (or payment.rejected if something is wrong) to the endpoint you configured.

Each webhook request carries these headers:

HeaderPurpose
X-Paysell-EventEvent type, e.g. payment.credited
X-Paysell-Event-IdUnique event ID, for deduplication
X-Paysell-TimestampUnix timestamp the request was signed at
X-Paysell-Signaturesha256=<hex> HMAC signature

Always verify the signature before trusting a webhook body. Here's a minimal Node.js example:

const crypto = require("crypto");

function verifyPaysellWebhook(rawBody, headers, secret) {
  const timestamp = headers["x-paysell-timestamp"];
  const signature = (headers["x-paysell-signature"] || "").replace("sha256=", "");

  const age = Math.abs(Date.now() / 1000 - Number(timestamp));
  if (age > 300) {
    throw new Error("Timestamp too old — possible replay");
  }

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.${rawBody}`)
    .digest("hex");

  const isValid = crypto.timingSafeEqual(
    Buffer.from(expected, "hex"),
    Buffer.from(signature, "hex")
  );

  if (!isValid) throw new Error("Invalid signature");
  return true;
}

Use rawBody — the unparsed request body — not a re-serialized JSON object, or the signature won't match. Reject anything older than 300 seconds, and use X-Paysell-Event-Id to ignore duplicates if a retry arrives after you've already processed the event.

Note: If your endpoint is down or returns an error, Paysell retries with backoff: 1 minute, 5 minutes, 15 minutes, 1 hour, 6 hours, then 24 hours, before giving up. You can always re-send a dropped event from the cabinet.

Step 6: Mark the order paid#

In your webhook handler, look up the order by order_id (or invoice_id), confirm the amount matches what you expected — remember, amounts in the webhook body are integers in minimal units — and update the order status. Respond with a 2xx status quickly; do any slow work (sending confirmation emails, updating inventory) after you've acknowledged the webhook.

That's the whole flow: create a store, generate a key, create an invoice, let the buyer pay through the hosted page, and let a verified webhook update your order. See the full API reference for invoice statuses, listing endpoints, and more detail on every field.

← All posts
Share

Start accepting USDT and TON

A merchant account, an API key and a hosted checkout page — 0.2% per payment, no monthly fee.

Create an account
On this page
  • Step 1: Create a store
  • Step 2: Create an API key
  • Step 3: Create an invoice with curl
  • Step 4: Open paymenturl
  • Step 5: Receive the webhook
  • Step 6: Mark the order paid
On this page
  • Step 1: Create a store
  • Step 2: Create an API key
  • Step 3: Create an invoice with curl
  • Step 4: Open paymenturl
  • Step 5: Receive the webhook
  • Step 6: Mark the order paid
Share

Related posts

How your payouts are protected at PaysellWhat happens to a withdrawal request after you hit the button: automated anti-fraud checks, isolated signing, cold storage — and the part that is up to you.TON vs. Tron for merchant paymentsA practical comparison of accepting USDT on TON versus USDT TRC-20 for merchants, and why Paysell started with TON.Introducing Paysell: accept USDT and TON on the TON networkPaysell is a payment processor built specifically for the TON network, giving merchants a cabinet, API, hosted checkout, and webhooks to accept USDT and Toncoin.
Paysell

Crypto payments for online business — fast, chargeback-free, no red tape.

Product

  • How it works
  • Pricing
  • Payment methods
  • Security
  • FAQ
  • Blog

Solutions

  • E-commerce
  • Digital goods
  • SaaS & subscriptions
  • Online education
  • Freelance & services
  • Games
  • iGaming
  • Trading platforms
  • All solutions

Developers

  • Documentation
  • Quick start
  • Webhooks
  • API reference (OpenAPI)
  • llms.txt for AI agents
  • 登录
  • 创建账户

Legal

  • Terms of Service
  • Privacy Policy
  • Fee Schedule and Limits
  • Acceptable Use Policy and Prohibited Businesses
  • AML/CTF and Sanctions Policy
  • Merchant Verification (KYC/KYB) Policy
  • Refunds, Disputes and Chargebacks
  • Crypto-Asset Risk Disclosure
  • All legal documents

© 2026 Paysell

Paysell is a crypto-asset payment service. Balances are not bank deposits, and the value of crypto-assets depends on the market.