Skip to content

Receiving payment results ​

Webhooks are the primary path for syncing payment results into your system. After a buyer completes payment, Taria Pay sends events to the webhook endpoint you configure.

Why webhooks are essential ​

If your site has order statuses, shipping, invoicing, membership access, or subscription entitlements, you should configure webhooks.

Don't rely solely on:

  • Whether the buyer returned to your successUrl
  • Whether the frontend page showed success
  • Support staff manually checking transactions

Your actual business records should be driven by webhooks or the query API.

Creating a webhook endpoint ​

In the Dashboard, go to Developers, then:

  1. Open Webhooks.
  2. Create an endpoint.
  3. Enter your publicly reachable callback URL, e.g. https://merchant.example/api/tariapay/webhook.
  4. Select the events you want to receive.
  5. Save the signing secret and store it in your server's environment variables.

We recommend subscribing to at least:

  • payment_intent.confirmed
  • payment_intent.failed
  • payment_intent.refunded
  • refund_request.created (if you want buyer refund requests synced into your own support system)

Whether the buyer pays with a wallet on the checkout page or with a direct transfer, the event types and payload structure are identical — your webhook handler doesn't need to distinguish between payment methods.

A compliance hold has no event of its own: a held payment still sends payment_intent.confirmed, and a hold that ends with the funds returned to the payer sends payment_intent.refunded. See Sanctions screening and compliance holds.

Request headers ​

HeaderDescription
x-tariapay-signature (x-pay-signature)HMAC-SHA256 of ${timestamp}.${rawBody}
x-tariapay-timestamp (x-pay-signature-timestamp)Unix timestamp in seconds
x-tariapay-event (x-pay-event)Event name
x-tariapay-delivery-id (x-pay-delivery-id)Unique delivery ID (dedupe key)

Signature verification with the SDK ​

You do not need a merchant secret key to verify webhooks.

ts
import { constructWebhookEvent } from "@tariapay/sdk";

export async function POST(req: Request) {
  const rawBody = await req.text();

  const event = constructWebhookEvent(
    rawBody,
    req.headers,
    process.env.TARIAPAY_WEBHOOK_SECRET!,
  );

  const paymentIntent = event.data.paymentIntent;

  switch (event.type) {
    case "payment_intent.confirmed":
      // Idempotently update the order by paymentId or orderId, then fulfill
      break;
    case "payment_intent.failed":
      // Mark the order failed and let the buyer pay again
      break;
    case "payment_intent.refunded":
      // Sync refund, inventory, and after-sales status
      break;
    case "refund_request.created":
      // Record data.refundRequest for merchant review; a request does not mean funds have been refunded
      break;
    default:
      break;
  }

  return Response.json({ received: true });
}

Example payload ​

json
{
  "id": "evt_123",
  "type": "payment_intent.confirmed",
  "createdAt": "2026-03-29T12:00:00.000Z",
  "data": {
    "paymentIntent": {
      "paymentId": "b1985d0b-2026-4f8c-bf75-59ea53fe5466",
      "orderId": "order_1001",
      "status": "confirmed",
      "currency": "USDC",
      "amount": "49.99",
      "checkoutUrl": "https://checkout.tariapay.com/pi_b1985d0b-2026-4f8c-bf75-59ea53fe5466",
      "txHash": "0x..."
    }
  }
}

Subscription events ​

If you use Subscriptions (API), you can also subscribe to the following events to keep subscription status in sync:

  • subscription.created
  • subscription.renewed
  • subscription.past_due
  • subscription.canceled

Their data contains subscription and invoice; use subscription.merchantCustomerId to link back to the customer in your own system.

Handling recommendations ​

  • Verify the signature before processing the payload.
  • Use paymentId or orderId for idempotent updates.
  • Return 2xx quickly; push slow work to your background queue.
  • Handle duplicate deliveries so you never ship twice or grant entitlements twice.
  • Check Delivery Logs for failure reasons and retry history.

Next steps ​