Documentation Index
Fetch the complete documentation index at: https://docs.crypto-cash.world/llms.txt
Use this file to discover all available pages before exploring further.
Fiat Webhooks
Note: all numeric values, amounts, and identifiers in the examples are illustrative and provided for demonstration purposes only.
Overview
Fiat Module uses Crypto-Cash webhooks, which are sent to the merchant after a transaction status changes. They work only if the webhookUrl parameter is configured on the Fiat API key. If webhookUrl is not set, webhooks are not sent.
The notification URL of the payment provider and the webhookUrl on the Fiat API key are different things. The webhookUrl on the Fiat API key is the address to which Crypto-Cash sends its events to the merchant.
Key parameters
| Parameter | Value |
|---|
| Crypto-Cash webhook target | webhookUrl configured on the Fiat API key |
| HTTP method | POST |
| Delivery | Asynchronous |
| Data format | application/json |
How webhooks work
User opens the payment widget
↓
Payment provider processes the payment
↓
Payment provider sends a webhook to Crypto-Cash
↓
Crypto-Cash verifies the provider signature
↓
Crypto-Cash updates the transaction status
↓
Crypto-Cash creates a payment event
↓
If webhookUrl is configured on the Fiat API key,
Crypto-Cash sends the webhook asynchronously
Crypto-Cash webhooks
Crypto-Cash webhooks are sent after payment events. They work only if webhookUrl is configured on the Fiat API key.
When a transaction status changes, the system creates a payment event and asynchronously sends a webhook to the configured webhookUrl. If webhookUrl is not configured, the webhook is not sent.
HTTP format:
Method: POST
Content-Type: application/json
Each webhook contains a signature field in the payload body. The merchant uses the Fiat API key to verify that the webhook was sent by Crypto-Cash and has not been modified.
The webhook payload and signature are stored for audit and history.
Event types
| Event | When it is sent | Type |
|---|
payment::created | Transaction created | Intermediate |
payment::waiting | Status changed to Waiting | Intermediate |
payment::paid | Status changed to Paid | Final |
payment::failed | Status changed to Fail | Final |
payment::canceled | Status changed to Canceled | Final |
Intermediate events (payment::created, payment::waiting) mean that the transaction is in progress and further status changes are possible.
Final events (payment::paid, payment::failed, payment::canceled) mean that the transaction has reached a terminal state:
| Final event | Meaning |
|---|
payment::paid | Cryptocurrency was successfully sent to the wallet address |
payment::failed | The payment was not completed |
payment::canceled | The payment was canceled |
What the merchant should check
When receiving a Crypto-Cash webhook:
- Verify the
signature field using the Fiat API key (see the “Webhook signature” section).
- Read
event.event_type to determine the event.
- Read
event.data — it contains the full transaction state.
- Process the event depending on whether it is intermediate or final.
The id field is unique for each webhook delivery. Use it for deduplication on your side.
Crypto-Cash webhook signature
Each Crypto-Cash webhook contains a signature field in the payload body.
The signature is generated from the webhook identifier and content:
payload = { id, delivered_at, event }
The merchant verifies the signature as follows: reconstruct the same payload from the received webhook, excluding the signature field, and verify it using the Fiat API key.
The verification method depends on the Fiat API key type:
ED25519 — verify the received signature using the Fiat API publicKey.
LEGACY — reconstruct the expected signature value using the Fiat API privateKey and compare it with the received one.
Use the same Fiat API key pair that is used for the merchant’s signed API requests. The private key must remain on the merchant side — do not send it in webhook responses, logs, or support requests.
Payload examples
payment::created
{
"id": "webhook-id",
"delivered_at": "2026-04-16T10:00:01.000Z",
"event": {
"event_type": "payment::created",
"timestamp": "2026-04-16T10:00:01.000Z",
"data": {
"id": "crypto-cash-transaction-id",
"externalId": "merchant-order-id",
"status": "New",
"fiatCurrency": "SGD",
"fiatAmount": "51",
"currency": "USDT",
"network": "TRC20",
"address": "wallet-address",
"cryptoAmount": null,
"exchangeRate": null,
"paymentMethod": null,
"hash": null,
"buyId": null,
"withdrawId": null,
"customerId": null,
"merchantEarning": null,
"merchantId": "merchant-id",
"createdAt": "2026-04-16T10:00:00.000Z",
"updatedAt": "2026-04-16T10:00:00.000Z"
}
},
"signature": "signature"
}
payment::waiting
{
"id": "webhook-id",
"delivered_at": "2026-04-16T10:00:15.000Z",
"event": {
"event_type": "payment::waiting",
"timestamp": "2026-04-16T10:00:15.000Z",
"data": {
"id": "crypto-cash-transaction-id",
"externalId": "merchant-order-id",
"status": "Waiting",
"fiatCurrency": "SGD",
"fiatAmount": "51",
"currency": "USDT",
"network": "TRC20",
"address": "wallet-address",
"cryptoAmount": null,
"exchangeRate": null,
"paymentMethod": "card",
"hash": null,
"buyId": "provider-operation-id",
"withdrawId": null,
"customerId": "customer-id",
"merchantEarning": null,
"merchantId": "merchant-id",
"createdAt": "2026-04-16T10:00:00.000Z",
"updatedAt": "2026-04-16T10:00:10.000Z"
}
},
"signature": "signature"
}
payment::paid
{
"id": "webhook-id",
"delivered_at": "2026-04-16T10:07:30.000Z",
"event": {
"event_type": "payment::paid",
"timestamp": "2026-04-16T10:07:30.000Z",
"data": {
"id": "crypto-cash-transaction-id",
"externalId": "merchant-order-id",
"status": "Paid",
"fiatCurrency": "SGD",
"fiatAmount": "51",
"currency": "USDT",
"network": "TRC20",
"address": "wallet-address",
"cryptoAmount": "50.12",
"exchangeRate": "1.02",
"paymentMethod": "card",
"hash": "blockchain-hash",
"buyId": "provider-operation-id",
"withdrawId": "provider-withdraw-id",
"customerId": "customer-id",
"merchantEarning": "0.9306",
"merchantId": "merchant-id",
"createdAt": "2026-04-16T10:00:00.000Z",
"updatedAt": "2026-04-16T10:07:00.000Z"
}
},
"signature": "signature"
}
payment::failed
{
"id": "webhook-id",
"delivered_at": "2026-04-16T10:02:05.000Z",
"event": {
"event_type": "payment::failed",
"timestamp": "2026-04-16T10:02:05.000Z",
"data": {
"id": "crypto-cash-transaction-id",
"externalId": "merchant-order-id",
"status": "Fail",
"fiatCurrency": "SGD",
"fiatAmount": "51",
"currency": "USDT",
"network": "TRC20",
"address": "wallet-address",
"cryptoAmount": null,
"exchangeRate": null,
"paymentMethod": "card",
"hash": null,
"buyId": "provider-operation-id",
"withdrawId": null,
"customerId": "customer-id",
"merchantEarning": null,
"merchantId": "merchant-id",
"createdAt": "2026-04-16T10:00:00.000Z",
"updatedAt": "2026-04-16T10:02:00.000Z"
}
},
"signature": "signature"
}
payment::canceled
{
"id": "webhook-id",
"delivered_at": "2026-04-16T10:03:05.000Z",
"event": {
"event_type": "payment::canceled",
"timestamp": "2026-04-16T10:03:05.000Z",
"data": {
"id": "crypto-cash-transaction-id",
"externalId": "merchant-order-id",
"status": "Canceled",
"fiatCurrency": "SGD",
"fiatAmount": "51",
"currency": "USDT",
"network": "TRC20",
"address": "wallet-address",
"cryptoAmount": null,
"exchangeRate": null,
"paymentMethod": "card",
"hash": null,
"buyId": "provider-operation-id",
"withdrawId": null,
"customerId": "customer-id",
"merchantEarning": null,
"merchantId": "merchant-id",
"createdAt": "2026-04-16T10:00:00.000Z",
"updatedAt": "2026-04-16T10:03:00.000Z"
}
},
"signature": "signature"
}