Skip to main content
When you create a payment order, the charge to the user’s account is processed later, in the batch TapiPay sends to the bank. The result reaches you through this webhook: one per movement of the charge.
This webhook has its own contract, different from the direct debit events: it does not carry operationId or companyName, and its idempotency key is id. What Common fields explains does not apply here, except for hash.

Two notices for a settled order

ORDER_PAYMENT_CONFIRMED reports the charge, not the payment of the debt. After confirming it, TapiPay applies the payment to the order’s debt and also sends you the payment notification (type: SERVICE, status: confirmed). So a settled order generates two notices, which can reach different URLs.

Configuration

The URL for these events is defined during onboarding and can be different from the one for the other webhooks. If you did not set one for orders, they reach your general URL. The security mechanisms are the same as for the rest of the webhooks: see Validating the request comes from TapiPay. POST with Content-Type: application/json. The notificationType header carries the same value as type, so you can route without reading the body.

The payload

In paymentMethod, the account type goes in type. In the order response and in GET /payment-methods the same value is called paymentMethodType. externalPaymentMethodId is the same value in all three places.
For now code and description always arrive as null inside paymentProviderError and chargeback. The object itself always comes in its event: read it without checking that it exists, but handle the null.

The hash

If you provided an RSA public key during onboarding, hash comes encrypted with it. Decrypt it with your private key: it contains your integration user or, in version v2 of the security, { "clientUsername", "operationId" }. In v2, check that operationId matches the id in the body.

Examples

An order that is charged and then reversed, and another whose charge is declined. The examples belong to an integration without a public key, which is why hash is null.

Recommendations

  • Process each notification only once. TapiPay retries if your endpoint does not answer 2xx in time, so the same notification can arrive more than once, always with the same id. Store the processed id values in persistent storage.
  • Do not assume an arrival order. Use paymentAt to order the movements of the same order.
  • Correlate by orderId or externalOrderId.
  • Ignore fields you do not know: new fields can be added.
  • If a webhook does not arrive, query the order with GET /v2/debts/orders.
The requirements for your endpoint (answer 2xx in under 5 seconds and be reachable from TapiPay’s IPs) are the same as for the rest of the webhooks: see Requirements for your endpoint.