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
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 whyhash 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 processedidvalues in persistent storage. - Do not assume an arrival order. Use
paymentAtto order the movements of the same order. - Correlate by
orderIdorexternalOrderId. - 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.

