Webhooks
Webhooks allow you to receive real-time notifications when events occur in your FYATU integration. Instead of polling for updates, your server receives HTTP POST requests when payments are received, cards are created, eSIMs are purchased, and more.
Setting Up Webhooks
Configure your webhook URL in two ways:
App-level webhook - Set in your app settings (takes priority)
Business-level webhook - Set in business settings (fallback)
# Update app webhook URL
curl -X PATCH "https://api.fyatu.com/api/v3/apps/{appId}/settings" \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{
"webhookUrl": "https://your-server.com/webhooks/fyatu",
"webhookSecret": "your_webhook_secret"
}'
Webhook Structure
All webhook payloads follow this structure:
{
"event" : "collection.received" ,
"version" : "2.0" ,
"sign" : "hmac_sha256_signature" ,
"data" : {
"reference" : "COL678A3B4C5D6E7" ,
"amount" : 100.00 ,
"appId" : "YOUR_APP_ID" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
Collection Events
collection.initiated
Triggered when a new payment collection is created.
{
"event" : "collection.initiated" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"reference" : "COL678A3B4C5D6E7" ,
"externalReference" : "ORDER-12345" ,
"amount" : 100.00 ,
"currency" : "USD" ,
"description" : "Order #12345" ,
"checkoutUrl" : "https://checkout.fyatu.com?batch=COL678A3B4C5D6E7" ,
"expiresAt" : "2026-01-12T19:30:00+00:00" ,
"status" : "PENDING" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
collection.received
Triggered when a payment is successfully received.
{
"event" : "collection.received" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"reference" : "COL678A3B4C5D6E7" ,
"externalReference" : "ORDER-12345" ,
"providerReference" : "PAY-20260112-ABC123" ,
"amount" : 100.00 ,
"charge" : 1.90 ,
"netAmount" : 98.10 ,
"currency" : "USD" ,
"paymentMethod" : "FYATU_BALANCE" ,
"customerEmail" : "[email protected] " ,
"customerPhone" : "+12025559999" ,
"customerName" : "John Doe" ,
"status" : "COMPLETED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
collection.failed
Triggered when a collection fails to process.
{
"event" : "collection.failed" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"reference" : "COL678A3B4C5D6E7" ,
"externalReference" : "ORDER-12345" ,
"amount" : 100.00 ,
"currency" : "USD" ,
"reason" : "Insufficient funds" ,
"status" : "FAILED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
collection.expired
Triggered when a collection expires without payment.
{
"event" : "collection.expired" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"reference" : "COL678A3B4C5D6E7" ,
"externalReference" : "ORDER-12345" ,
"amount" : 100.00 ,
"currency" : "USD" ,
"status" : "EXPIRED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
Payout Events
payout.initiated
Triggered when a payout is created.
{
"event" : "payout.initiated" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"reference" : "PAY678A3B4C5D6E7" ,
"externalReference" : "PAYOUT-12345" ,
"amount" : 50.00 ,
"charge" : 0.50 ,
"currency" : "USD" ,
"accountNumber" : "CLT123456789" ,
"accountName" : "Jane Doe" ,
"country" : "CD" ,
"status" : "PENDING" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
payout.completed
Triggered when a payout is successfully completed.
{
"event" : "payout.completed" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"reference" : "PAY678A3B4C5D6E7" ,
"externalReference" : "PAYOUT-12345" ,
"amount" : 50.00 ,
"charge" : 0.50 ,
"netAmount" : 49.50 ,
"currency" : "USD" ,
"accountNumber" : "CLT123456789" ,
"accountName" : "Jane Doe" ,
"status" : "COMPLETED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
payout.failed
Triggered when a payout fails.
{
"event" : "payout.failed" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"reference" : "PAY678A3B4C5D6E7" ,
"externalReference" : "PAYOUT-12345" ,
"amount" : 50.00 ,
"currency" : "USD" ,
"reason" : "Recipient account not found" ,
"status" : "FAILED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
Refund Events
refund.initiated
Triggered when a refund is created.
{
"event" : "refund.initiated" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"refundId" : "REF678A3B4C5D6E7" ,
"collectionId" : "COL678A3B4C5D6E7" ,
"amount" : 100.00 ,
"currency" : "USD" ,
"reason" : "CUSTOMER_REQUEST" ,
"reasonDescription" : "Customer changed their mind" ,
"mode" : "FULL" ,
"recipient" : {
"clientId" : "CLT123456789" ,
"name" : "John Doe"
},
"status" : "PENDING" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
refund.completed
Triggered when a refund is successfully processed.
{
"event" : "refund.completed" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"refundId" : "REF678A3B4C5D6E7" ,
"collectionId" : "COL678A3B4C5D6E7" ,
"amount" : 100.00 ,
"currency" : "USD" ,
"reason" : "CUSTOMER_REQUEST" ,
"reasonDescription" : "Customer changed their mind" ,
"recipient" : {
"clientId" : "CLT123456789" ,
"name" : "John Doe"
},
"status" : "COMPLETED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
refund.failed
Triggered when a refund fails.
{
"event" : "refund.failed" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"refundId" : "REF678A3B4C5D6E7" ,
"collectionId" : "COL678A3B4C5D6E7" ,
"amount" : 100.00 ,
"currency" : "USD" ,
"reason" : "Insufficient business balance" ,
"status" : "FAILED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
eSIM Events
esim.purchased
Triggered when an eSIM is purchased.
{
"event" : "esim.purchased" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"esimId" : "ESM678A3B4C5D6E7" ,
"iccid" : "8901234567890123456" ,
"batch" : "BES678A3B4C5D6E7" ,
"packageName" : "France 5GB - 30 Days" ,
"dataAmount" : "5 GB" ,
"validity" : "30 days" ,
"countries" : [ "France" ],
"amount" : 15.00 ,
"charge" : 0.00 ,
"currency" : "USD" ,
"status" : "SUCCESS" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
esim.topped_up
Triggered when an eSIM is topped up.
{
"event" : "esim.topped_up" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"esimId" : "ESM678A3B4C5D6E7" ,
"iccid" : "8901234567890123456" ,
"packageName" : "France Top-Up 2GB" ,
"dataAmount" : "2 GB" ,
"validity" : "30 days" ,
"amount" : 8.00 ,
"currency" : "USD" ,
"status" : "SUCCESS" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
esim.activated
Triggered when an eSIM is activated (first use in coverage area).
{
"event" : "esim.activated" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"esimId" : "ESM678A3B4C5D6E7" ,
"iccid" : "8901234567890123456" ,
"activatedAt" : "2026-01-12T18:30:00+00:00" ,
"expiresAt" : "2026-02-11T18:30:00+00:00" ,
"status" : "ACTIVE" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
esim.data_warning
Triggered when data usage reaches 80%.
{
"event" : "esim.data_warning" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"esimId" : "ESM678A3B4C5D6E7" ,
"iccid" : "8901234567890123456" ,
"dataUsedMb" : 4096 ,
"dataTotalMb" : 5120 ,
"percentUsed" : 80 ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
esim.data_exhausted
Triggered when data is fully consumed.
{
"event" : "esim.data_exhausted" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"esimId" : "ESM678A3B4C5D6E7" ,
"iccid" : "8901234567890123456" ,
"dataUsedMb" : 5120 ,
"dataTotalMb" : 5120 ,
"status" : "DATA_EXHAUSTED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
esim.expired
Triggered when an eSIM validity period ends.
{
"event" : "esim.expired" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"esimId" : "ESM678A3B4C5D6E7" ,
"iccid" : "8901234567890123456" ,
"expiredAt" : "2026-02-11T18:30:00+00:00" ,
"status" : "EXPIRED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-02-11T18:30:00+00:00"
}
}
Card Events (Issuing)
card.created
Triggered when a new virtual card is created.
{
"event" : "card.created" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"cardId" : "CRD678A3B4C5D6E7" ,
"cardholderId" : "ch_abc123xyz" ,
"type" : "VIRTUAL" ,
"brand" : "MASTERCARD" ,
"currency" : "USD" ,
"last4" : "4532" ,
"status" : "ACTIVE" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
card.funded
Triggered when funds are added to a card.
{
"event" : "card.funded" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"cardId" : "CRD678A3B4C5D6E7" ,
"cardholderId" : "ch_abc123xyz" ,
"reference" : "my-order-12345" ,
"amount" : 100.00 ,
"newBalance" : 150.00 ,
"currency" : "USD" ,
"status" : "SUCCESS" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
The reference field contains your custom reference if provided during the fund request, or defaults to the cardId.
card.unloaded
Triggered when funds are withdrawn from a card.
{
"event" : "card.unloaded" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"cardId" : "CRD678A3B4C5D6E7" ,
"cardholderId" : "ch_abc123xyz" ,
"reference" : "withdraw-67890" ,
"amount" : 50.00 ,
"newBalance" : 100.00 ,
"currency" : "USD" ,
"status" : "SUCCESS" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
The reference field contains your custom reference if provided during the unload request, or defaults to the cardId.
card.frozen
Triggered when a card is frozen.
{
"event" : "card.frozen" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"cardId" : "CRD678A3B4C5D6E7" ,
"reason" : "User requested" ,
"status" : "FROZEN" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
card.unfrozen
Triggered when a frozen card is unfrozen.
{
"event" : "card.unfrozen" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"cardId" : "CRD678A3B4C5D6E7" ,
"status" : "ACTIVE" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
card.terminated
Triggered when a card is permanently terminated.
{
"event" : "card.terminated" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"cardId" : "CRD678A3B4C5D6E7" ,
"cardholderId" : "ch_abc123xyz" ,
"cardName" : "John Doe" ,
"last4" : "4532" ,
"reference" : "cancel-card-abc123" ,
"status" : "TERMINATED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
The reference field contains your custom reference if provided during the terminate request, or defaults to the cardId.
card.replaced
Triggered when a card is replaced with a new card (same cardId, new card details).
{
"event" : "card.replaced" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"cardId" : "CRD678A3B4C5D6E7" ,
"cardholderId" : "ch_abc123xyz" ,
"cardName" : "John Doe" ,
"last4" : "7891" ,
"brand" : "MASTERCARD" ,
"status" : "ACTIVE" ,
"previousLast4" : "4532" ,
"reason" : "Card compromised" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
Card replacement creates a new physical/virtual card while keeping the same cardId for your records. The previous card is automatically terminated.
card.transaction.approved
Triggered when a card purchase is approved.
{
"event" : "card.transaction.approved" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"cardId" : "CRD678A3B4C5D6E7" ,
"reference" : "TXN550e8400e29b41d4" ,
"amount" : 49.99 ,
"currency" : "USD" ,
"merchant" : {
"name" : "AMAZON *MARKETPLACE" ,
"category" : "SHOPPING" ,
"country" : "US"
},
"cardBalanceBefore" : 150.00 ,
"cardBalanceAfter" : 100.01 ,
"status" : "APPROVED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
card.transaction.declined
Triggered when a card purchase is declined.
{
"event" : "card.transaction.declined" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"cardId" : "CRD678A3B4C5D6E7" ,
"reference" : "TXN550e8400e29b41d4" ,
"amount" : 299.99 ,
"currency" : "USD" ,
"merchant" : {
"name" : "BESTBUY" ,
"category" : "ELECTRONICS"
},
"reason" : "Insufficient funds" ,
"status" : "DECLINED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
card.transaction.reversed
Triggered when a card transaction is refunded by merchant.
{
"event" : "card.transaction.reversed" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"cardId" : "CRD678A3B4C5D6E7" ,
"reference" : "REV550e8400e29b41d4" ,
"originalReference" : "TXN550e8400e29b41d4" ,
"amount" : 49.99 ,
"currency" : "USD" ,
"status" : "REVERSED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-12T18:30:00+00:00"
}
}
Cardholder Events (Issuing)
cardholder.created
Triggered when a new cardholder is created.
{
"event" : "cardholder.created" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"cardholderId" : "ch_1a2b3c4d5e6f7890abcdef1234567890" ,
"firstName" : "John" ,
"lastName" : "Smith" ,
"email" : "[email protected] " ,
"phone" : "+12025551234" ,
"status" : "ACTIVE" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-15T21:31:39+00:00"
}
}
cardholder.kyc_submitted
Triggered when KYC documents are submitted for a cardholder.
{
"event" : "cardholder.kyc_submitted" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"cardholderId" : "ch_1a2b3c4d5e6f7890abcdef1234567890" ,
"firstName" : "John" ,
"lastName" : "Smith" ,
"documentType" : "PASSPORT" ,
"kycStatus" : "PENDING" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-15T22:00:00+00:00"
}
}
cardholder.kyc_approved
Triggered when cardholder KYC verification is approved.
{
"event" : "cardholder.kyc_approved" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"cardholderId" : "ch_1a2b3c4d5e6f7890abcdef1234567890" ,
"firstName" : "John" ,
"lastName" : "Smith" ,
"kycLevel" : "VERIFIED" ,
"kycStatus" : "VERIFIED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-16T10:00:00+00:00"
}
}
cardholder.kyc_rejected
Triggered when cardholder KYC verification is rejected.
{
"event" : "cardholder.kyc_rejected" ,
"version" : "2.0" ,
"sign" : "..." ,
"data" : {
"cardholderId" : "ch_1a2b3c4d5e6f7890abcdef1234567890" ,
"firstName" : "John" ,
"lastName" : "Smith" ,
"reason" : "Document image is unclear" ,
"status" : "REJECTED" ,
"appId" : "D0H6R7Z6R1C2N5O5" ,
"timestamp" : "2026-01-16T10:00:00+00:00"
}
}
Verifying Signatures
All webhooks include an HMAC-SHA256 signature. Verify using your webhook secret:
const crypto = require ( 'crypto' );
function verifySignature ( data , signature , secret ) {
const expected = crypto
. createHmac ( 'sha256' , secret )
. update ( JSON . stringify ( data ))
. digest ( 'hex' );
return crypto . timingSafeEqual (
Buffer . from ( signature ),
Buffer . from ( expected )
);
}
app . post ( '/webhooks/fyatu' , ( req , res ) => {
const { sign , data } = req . body ;
if ( ! verifySignature ( data , sign , process . env . WEBHOOK_SECRET )) {
return res . status ( 401 ). json ({ error: 'Invalid signature' });
}
// Respond immediately
res . status ( 200 ). send ( 'OK' );
// Process asynchronously
processWebhook ( req . body );
});
Event Summary
Collection Events
Event Description collection.initiatedPayment request created collection.receivedPayment successfully received collection.failedPayment failed collection.expiredPayment request expired
Payout Events
Event Description payout.initiatedPayout request created payout.completedPayout successfully sent payout.failedPayout failed
Refund Events
Event Description refund.initiatedRefund request created refund.completedRefund successfully processed refund.failedRefund failed
eSIM Events
Event Description esim.purchasedeSIM purchased esim.topped_upeSIM topped up esim.activatedeSIM activated esim.data_warningData usage at 80% esim.data_exhaustedData fully consumed esim.expiredeSIM validity ended
Card Events (Issuing)
Event Description card.createdNew card created card.fundedCard funded card.unloadedCard unloaded card.frozenCard frozen card.unfrozenCard unfrozen card.terminatedCard terminated card.replacedCard replaced with new card card.transaction.approvedTransaction approved card.transaction.declinedTransaction declined card.transaction.reversedTransaction reversed
Cardholder Events (Issuing)
Event Description cardholder.createdNew cardholder created cardholder.kyc_submittedKYC documents submitted cardholder.kyc_approvedKYC verification approved cardholder.kyc_rejectedKYC verification rejected
Best Practices
Respond Quickly Return 200 OK within 5 seconds to avoid retries
Verify Signatures Always verify HMAC signatures before processing
Handle Idempotency Use reference fields to handle duplicate webhooks
Process Async Queue webhooks for reliable background processing