Webhooks

Events

Catalog of TuCapi Business webhook events and the data each one carries.

Catalog

EventWhen
order.createdYour customer picked a payment method and a pending order was created.
order.paidThe payment was confirmed and the net amount credited to your balance.
order.expiredThe order expired without being paid.
payout.createdYou requested a payout.
payout.completedThe payout was confirmed on-chain.
payout.failedThe payout failed and the balance was returned.
subscription.*Recurring billing: created, installment generated, paid or overdue, paused, resumed, cancelled and ended. See below.
webhook.testManual test from the dashboard. You can't subscribe to it.

Order events

Eventdata fields
order.createdorderId, merchantOrderRef, amount, currency, paymentMethod, status, paymentLinkId (charge id), expiresAt, createdAt, source, store (store sales only)
order.paidorderId, merchantOrderRef, amount, currency, paymentMethod, netUsdt, externalRef, customerEmail, paidAt, source, store (store sales only), meta (optional, depends on the method)
order.expiredorderId, merchantOrderRef, amount, currency, paymentMethod, paymentLinkId, expiresAt, hadRailAssignment

Values don't use the API's format

In webhooks, paymentMethod is uppercase: PAYPAL, ZELLE, STRIPE (card) or, for peso payments, BRIDGE_COP and BRIDGE_MXN. The status in order.created is PENDING. And amount doesn't always have two decimals.

order.expired also covers orders that failed to start the payment (hadRailAssignment: false).

order.paid
JSON
{  "id": "evt_2b1c9d0e4f5a4a6b8c7d9e0f1a2b3c4d",  "type": "order.paid",  "createdAt": "2026-09-15T18:50:31Z",  "merchantId": "3e630ae9-6ee0-4ee7-b40c-1ea853829377",  "data": {    "orderId": "c9227f9b-13f4-4e9c-8fe0-4644e62b83cd",    "merchantOrderRef": "MO-k7x2m9qz-1a2b3c4d",    "amount": "125.00",    "currency": "USD",    "paymentMethod": "PAYPAL",    "netUsdt": "120.33",    "externalRef": "5O190127TN364715T",    "customerEmail": "ana@example.com",    "paidAt": "2026-09-15T18:50:31Z",    "source": "payment_link"  }}

Where the order came from

order.created and order.paid carry source, which says where the order came from:

sourceThe order came from
payment_linkA payment link you made in the dashboard.
invoiceAn invoice.
storeA sale from your store. Carries store, below.
subscriptionA recurring payment installment.
apiA charge created with the API (POST /v1/charges).
manualAdded by the TuCapi team, for example a deposit assigned by hand.

If you get a value you don't know, treat it as payment_link: the list may grow.

Store sales

When source is store, you also get store with the order:

FieldWhat it is
orderIdThe store order id (not the payment order id).
numberThe order number, as you see it in Orders. It's null in order.created: it's assigned when paid.
itemsThe products: productId, variantId and variant (the chosen size or color, null if the product has none), name, quantity, unitPrice and lineTotal. productId is null if you deleted the product.
subtotal, discount, deliveryFee, totalThe order amounts, as text with two decimals.
couponCodeThe coupon used, or null.
deliveryMethodPICKUP (pickup), DELIVERY (home delivery) or SHIPPING (nationwide shipping).
customername, phone, address and note. Address and note may be null.
order.paid (store)
JSON
{  "id": "evt_7c3d1e2f4a5b4c6d8e9f0a1b2c3d4e5f",  "type": "order.paid",  "createdAt": "2026-10-27T15:12:09Z",  "merchantId": "3e630ae9-6ee0-4ee7-b40c-1ea853829377",  "data": {    "orderId": "c9227f9b-13f4-4e9c-8fe0-4644e62b83cd",    "merchantOrderRef": "MO-t4n8p2wd-9f8e7d6c",    "amount": "32.00",    "currency": "USD",    "paymentMethod": "STRIPE",    "netUsdt": "29.76",    "externalRef": "pi_3Q…",    "customerEmail": "ana@example.com",    "paidAt": "2026-10-27T15:12:09Z",    "source": "store",    "store": {      "orderId": "8b0e5d1c-2f3a-4b5c-9d6e-7f8a9b0c1d2e",      "number": 42,      "items": [        {          "productId": "1f2a3b4c-5d6e-4f70-8192-a3b4c5d6e7f8",          "name": "Chocolate cake",          "quantity": 2,          "unitPrice": "15.00",          "lineTotal": "30.00"        }      ],      "subtotal": "30.00",      "discount": "3.00",      "couponCode": "WELCOME",      "deliveryFee": "5.00",      "total": "32.00",      "currency": "USD",      "deliveryMethod": "DELIVERY",      "customer": {        "name": "Ana Pérez",        "phone": "584121234567",        "address": "123 Main St, Miami",        "note": "Ring 2B"      }    }  }}

Payout events

Eventdata fields
payout.createdpayoutId, amountUsdt, feeUsdt, netUsdt, destinationAddress, network, status, createdAt
payout.completedpayoutId, amountUsdt, feeUsdt, netUsdt, destinationAddress, network, txHash
payout.failedpayoutId, amountUsdt, feeUsdt, netUsdt, destinationAddress, network, refunded
  • amountUsdt is what was debited from your balance.
  • feeUsdt is the payout fee.
  • netUsdt is what's sent: amountUsdt = feeUsdt + netUsdt.
  • If the payout fails, the full amountUsdt is returned, fee included.

Recurring billing events

PRO and PREMIUM plans only. data.subscription has the shape of a subscription (without installments) and data.installment, that of an installment. Paying each installment also emits the usual order.* events.

EventWhendata fields
subscription.createdYou subscribed a customer, from the dashboard or the API.subscription
subscription.installment.createdThe period's installment was generated, a few days before the due date depending on the plan.subscription, installment (with checkoutUrl)
subscription.installment.paidYour customer paid the installment.subscription, installment (with orderId)
subscription.installment.overdueThe installment went unpaid past its due date (the day after).subscription, installment
subscription.pausedYou paused the subscription.subscription
subscription.resumedYou resumed it. Paused periods aren't charged.subscription
subscription.cancelledYou cancelled it: pending installments are voided.subscription
subscription.endedThe last installment of a plan with a fixed number of installments was paid.subscription

Declared, not emitted yet

You can subscribe to these events, but they won't arrive until the flow that produces them exists. The dashboard shows them disabled.

EventWhy it doesn't arrive
order.cancelledThere's no order cancellation.
order.refundedThere's no refund flow.
merchant.kyb.approvedThe verification result only shows in the dashboard.
merchant.kyb.rejectedThe verification result only shows in the dashboard.