Get started
Create your first charge
Create a charge with the API, send your customer to checkout and confirm the payment by webhook. In five minutes.
1Get an API key
Create a Secret, Live key with the orders:write scope (and orders:read if you'll retrieve charges). The steps are in Authentication.
# Keep it in a server environment variableexport TUCAPI_KEY=tcb_sk_live_…2Create the charge
From your server, call POST /v1/charges. Only amount is required.
amountstringRequiredAmount in USD. Greater than 0, up to 2 decimals and up to 1,000,000. Send it as a string:"125.00".descriptionstringOptionalWhat your customer sees at checkout. Up to 200 characters.referencestringOptionalYour order or invoice number. Up to 120 characters. Unique per merchant.metadataobjectOptionalYour own data. Up to 20 keys and 4 KB. Returned as is.allowedMethodsstring[]Optionalpaypal,zelle,card. If you leave it out, every method you have enabled is offered.expiresAtstring (date-time)OptionalUp to one year. After that date, checkout stops accepting payments.
Note
Idempotency-Key header. If the connection drops and you retry, no second charge is created. More in Idempotency.curl -X POST https://api.business.tucapi.com/v1/charges \ -H "Authorization: Bearer $TUCAPI_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: ORD-1042" \ -d '{ "amount": "125.00", "description": "Pedido #1042", "reference": "ORD-1042", "metadata": { "customerId": "c_88" }, "allowedMethods": [ "paypal", "card" ], "expiresAt": "2026-09-16T12:00:00Z" }'{ "object": "charge", "id": "9b1e2d3c-4f5a-4b6c-8d7e-0f1a2b3c4d5e", "status": "open", "amount": "125.00", "currency": "USD", "description": "Pedido #1042", "reference": "ORD-1042", "metadata": { "customerId": "c_88" }, "allowedMethods": [ "paypal", "card" ], "checkoutUrl": "https://pay.tucapi.com/k7x2m9qz", "embedUrl": "https://pay.tucapi.com/embed/k7x2m9qz", "expiresAt": "2026-09-16T12:00:00Z", "paidAt": null, "createdAt": "2026-09-15T18:42:07Z", "orders": []}3Send your customer to checkout
Redirect your customer to checkoutUrl. You can also send them the link by WhatsApp or email.
There they pick a payment method from allowedMethods.
- A charge can be paid once: it has at most one paid order.
- Want the payment to happen inside your site? Use
embedUrlwith the embedded checkout.
// Expressapp.post("/checkout", async (req, res) => { const charge = await createCharge(req.body); // POST /v1/charges res.redirect(303, charge.checkoutUrl);});4Confirm the payment by webhook
In the dashboard, go to Webhooks and create an endpoint subscribed to order.paid.
When the payment is confirmed, you get a signed POST. Your endpoint should:
- 1Verify the signature in the
TuCapi-Signatureheader. - 2Skip the event if you've already processed that
id. - 3Answer
2xxwithin 10 seconds.
order.paid doesn't include the charge id
orderId. Call GET /v1/orders/{orderId}: the order has chargeId. The order.created event does include the charge, as paymentLinkId.Details in Receive webhooks.
// Express: use the RAW body, not parsed JSONapp.post( "/webhooks/tucapi", express.raw({ type: "application/json" }), (req, res) => { try { verifyTuCapi(req.body, req.get("TuCapi-Signature"), process.env.TUCAPI_WEBHOOK_SECRET); } catch { return res.sendStatus(400); } const event = JSON.parse(req.body); if (alreadyProcessed(event.id)) return res.sendStatus(200); // dedupe if (event.type === "order.paid") { // order.paid has no charge id; the order does (chargeId). // Queue it and call GET /v1/orders/{orderId} later. queuePayment(event.data.orderId); } res.sendStatus(200); // answer fast; process later },);5Retrieve the charge
Can't receive webhooks? Retrieve the charge. Its status changes to paid when one of its orders is confirmed.
Note
curl "https://api.business.tucapi.com/v1/charges/9b1e2d3c-4f5a-4b6c-8d7e-0f1a2b3c4d5e" \ -H "Authorization: Bearer $TUCAPI_KEY"{ "object": "charge", "id": "9b1e2d3c-4f5a-4b6c-8d7e-0f1a2b3c4d5e", "status": "paid", "amount": "125.00", "currency": "USD", "description": "Pedido #1042", "reference": "ORD-1042", "metadata": { "customerId": "c_88" }, "allowedMethods": [ "paypal", "card" ], "checkoutUrl": "https://pay.tucapi.com/k7x2m9qz", "embedUrl": "https://pay.tucapi.com/embed/k7x2m9qz", "expiresAt": "2026-09-16T12:00:00Z", "paidAt": "2026-09-15T18:50:31Z", "createdAt": "2026-09-15T18:42:07Z", "orders": [ { "object": "order", "id": "c9227f9b-13f4-4e9c-8fe0-4644e62b83cd", "chargeId": "9b1e2d3c-4f5a-4b6c-8d7e-0f1a2b3c4d5e", "merchantOrderRef": "MO-k7x2m9qz-1a2b3c4d", "status": "paid", "paymentMethod": "paypal", "amount": "125.00", "currency": "USD", "fees": { "rate": "0.035", "fixed": "0.30" }, "netAmountUsdt": "120.33", "externalRef": "5O190127TN364715T", "payer": { "email": "ana@example.com", "name": null }, "expiresAt": "2026-09-15T19:12:07Z", "paidAt": "2026-09-15T18:50:31Z", "createdAt": "2026-09-15T18:42:07Z" } ]}Before going live
- 1A live secret key with just the scopes you need, stored on the server.
- 2
POST /v1/chargeswithIdempotency-Keyandreferenceset to your order number. - 3Redirect to
checkoutUrl. - 4A webhook endpoint that verifies the signature, dedupes by
idand answers2xxfast. - 5On
order.paid, mark the order as paid (find the charge through the order). - 6Daily reconciliation with
GET /v1/orders?status=paid.