Developers

A stablecoin payments API with no surprises.

Create an invoice on your server, send the payer to the checkout, fulfil on a signed webhook. That is the whole integration.

Create an invoice

Price it in dollars. Tillsafe works out the exact amount for every asset and network you accept, and reserves a deposit address for this invoice alone.

curlShell
curl "$TILLSAFE_API/v1/invoices" \
  -H "Authorization: Bearer $TILLSAFE_SECRET_KEY" \
  -H "Idempotency-Key: order-1001" \
  -H "Content-Type: application/json" \
  -d '{"amount": "30.00", "currency": "USD", "description": "Order #1001",
       "metadata": {"order_id": "1001"}}'
Node.jsJavaScript
const res = await fetch(`${process.env.TILLSAFE_API}/v1/invoices`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.TILLSAFE_SECRET_KEY}`,
    "Idempotency-Key": `order-${order.id}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    amount: "30.00",
    currency: "USD",
    description: `Order #${order.id}`,
    metadata: { order_id: String(order.id) },
  }),
});
const invoice = await res.json(); // id, status, payment_options, expires_at

Early-access merchants get their API address and keys with their account.

Hard to get wrong

  • Money is a string

    {"amount": "30.00", "currency": "USD"}. Never a JSON number, so nothing is rounded by a float.

  • Retries are safe

    Every write takes an Idempotency-Key. Repeat a request and you get the first response back.

  • One error shape

    A type, a stable code to branch on, a readable message and a link to the docs.

  • Signed webhooks with replay

    HMAC-SHA256 over a timestamp and the body. Retried for about 72 hours. Every attempt logged, any one replayable.

  • Live status events

    Follow an invoice over Server-Sent Events, and resume after a dropped connection without missing a step.

  • Test mode on real testnets

    Test keys see only testnets, such as TRON Nile. A test helper pays an invoice through the real pipeline, so your webhooks see what a real payment sends.

What the API covers

Resource What you can do
Invoices Create, list, cancel; accept or reject a held payment; follow live status
Payments List every on-chain transfer matched to your invoices
Refunds Create, cancel, mark sent; the payer claims through a private link
Payment links Fixed or payer-chosen amounts, with quantity limits
Plans, customers, subscriptions Bill each period with an invoice; pause, resume, cancel; prepaid credit
Reconciliation Reconcile a period, read balances as of a date, export CSV
Webhook deliveries Inspect every attempt and replay any of them

The API is described in OpenAPI, and the reference is generated from it.

Questions developers ask

Do I handle wrong networks and short payments myself?

No, the invoice does. Its status says paid, partially_paid, overpaid, paid_late, under_review or expired. Fulfil on invoice.paid.

Can a payer fake a payment with a transaction ID?

No. Payments are matched by the address they arrived at, which belongs to one invoice at a time. A transaction ID never credits anything.

Is there an SDK?

Early-access merchants get a TypeScript client generated from the OpenAPI document, with a webhook verifier. The docs have webhook receivers in Node.js, Python, PHP and Go.

Do the docs match the API?

Our test suite runs the quickstart and the Node.js and Python webhook examples against a real server.