Event Types
FLUID Network sends webhooks for various transaction lifecycle events. This page describes each event type, when it's triggered, and what data it contains.
Transaction Lifecycle Events
Transaction events follow the payment processing lifecycle from creation to completion or failure.
Event Flow
transaction.created
Description
Triggered when a debit or credit transaction is initially created in the FLUID system, before any processing begins.
When Triggered
- Payment provider submits a new debit transaction via API
- Bank initiates a credit transaction
- Immediately after API request validation succeeds
Use Cases
- Log transaction initiation
- Display "pending" status to customers
- Track transaction creation metrics
Example Payload
{
"event": "transaction.created",
"event_id": "evt_c1a2b3d4e5f6g7h8",
"timestamp": "2025-01-28T10:15:00Z",
"api_version": "v1",
"data": {
"transaction": {
"id": "dt_12345",
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"reference": "FLU-20250128-ABC123",
"partner_reference": "ORDER-67890",
"status": "created",
"amount": 100.0,
"currency": "GHS",
"fee": 1.5,
"narration": "Payment for Order #67890",
"approval_method": "ussd",
"bank": {
"name": "Example Bank Ghana",
"identifier": "EXB",
"country_code": "GH"
},
"customer": {
"name": "Kwame Mensah",
"phone_number": "+233241234567"
},
"created_at": "2025-01-28T10:15:00Z",
"processed_at": null,
"completed_at": null
},
"previous_status": null,
"metadata": {
"order_id": "67890",
"customer_email": "kwame@example.com"
}
}
}transaction.pending
Description
Triggered when a transaction is validated and queued for bank submission. The transaction has passed initial checks and is waiting to be sent to the bank.
When Triggered
- After transaction creation and internal validation
- Before submission to the bank's API
- Typically within seconds of
transaction.created
Use Cases
- Update UI to show "processing" state
- Log queue timing metrics
- Prepare for bank processing
Example Payload
{
"event": "transaction.pending",
"event_id": "evt_d2e3f4g5h6i7j8k9",
"timestamp": "2025-01-28T10:15:05Z",
"api_version": "v1",
"data": {
"transaction": {
"id": "dt_12345",
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"reference": "FLU-20250128-ABC123",
"partner_reference": "ORDER-67890",
"status": "pending",
"amount": 100.0,
"currency": "GHS",
"fee": 1.5,
"narration": "Payment for Order #67890",
"bank": {
"name": "Example Bank Ghana",
"identifier": "EXB",
"country_code": "GH"
},
"customer": {
"name": "Kwame Mensah",
"phone_number": "+233241234567"
},
"created_at": "2025-01-28T10:15:00Z",
"processed_at": null,
"completed_at": null
},
"previous_status": "created",
"metadata": {
"order_id": "67890",
"customer_email": "kwame@example.com"
}
}
}transaction.processing
Description
Triggered when the transaction has been successfully submitted to the bank's API and is being processed by the bank.
When Triggered
- After successful submission to bank API
- Bank has accepted the request
- Waiting for final bank confirmation (callback or polling)
Use Cases
- Update transaction status to "processing"
- Display estimated completion time to customers
- Monitor bank processing duration
Example Payload
{
"event": "transaction.processing",
"event_id": "evt_e3f4g5h6i7j8k9l0",
"timestamp": "2025-01-28T10:15:12Z",
"api_version": "v1",
"data": {
"transaction": {
"id": "dt_12345",
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"reference": "FLU-20250128-ABC123",
"partner_reference": "ORDER-67890",
"status": "processing",
"amount": 100.0,
"currency": "GHS",
"fee": 1.5,
"narration": "Payment for Order #67890",
"bank_reference": "BNK-REF-789012",
"bank": {
"name": "Example Bank Ghana",
"identifier": "EXB",
"country_code": "GH"
},
"customer": {
"name": "Kwame Mensah",
"phone_number": "+233241234567"
},
"created_at": "2025-01-28T10:15:00Z",
"processed_at": "2025-01-28T10:15:12Z",
"completed_at": null
},
"previous_status": "pending",
"metadata": {
"order_id": "67890",
"customer_email": "kwame@example.com"
}
}
}Bank Reference Available
Once a transaction reaches processing status, the bank_reference field is populated with the bank's unique transaction identifier.
transaction.completed ✅
Description
Triggered when the bank confirms successful transaction processing. This is the final success state for a transaction.
When Triggered
- Bank sends success callback/confirmation
- Funds have been debited from customer account (for debits)
- Funds have been credited to customer account (for credits)
Use Cases
- Mark transaction as successful in your system
- Send success notification to customer (SMS/email)
- Fulfill order or deliver service
- Update account balances
- Generate receipts
Example Payload
{
"event": "transaction.completed",
"event_id": "evt_f4g5h6i7j8k9l0m1",
"timestamp": "2025-01-28T10:15:45Z",
"api_version": "v1",
"data": {
"transaction": {
"id": "dt_12345",
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"reference": "FLU-20250128-ABC123",
"partner_reference": "ORDER-67890",
"status": "completed",
"amount": 100.0,
"currency": "GHS",
"fee": 1.5,
"narration": "Payment for Order #67890",
"approval_method": "ussd",
"bank_reference": "BNK-REF-789012",
"bank": {
"name": "Example Bank Ghana",
"identifier": "EXB",
"country_code": "GH"
},
"customer": {
"name": "Kwame Mensah",
"phone_number": "+233241234567"
},
"created_at": "2025-01-28T10:15:00Z",
"processed_at": "2025-01-28T10:15:12Z",
"completed_at": "2025-01-28T10:15:45Z"
},
"previous_status": "processing",
"metadata": {
"order_id": "67890",
"customer_email": "kwame@example.com"
}
}
}Most Important Event
transaction.completed is the most critical webhook event. This is when you should update your records, fulfill orders, and notify customers of success.
transaction.failed ❌
Description
Triggered when transaction processing fails at any stage. This is a terminal failure state requiring user action or retry.
When Triggered
- Bank rejects the transaction
- Customer declines USSD prompt
- Insufficient funds in customer account
- Invalid account/phone number
- Network timeout or connectivity issues
- Bank system unavailable
Use Cases
- Mark transaction as failed in your system
- Send failure notification to customer
- Display error message with reason
- Suggest remediation (retry, check account, etc.)
- Log failure metrics for monitoring
Example Payload
{
"event": "transaction.failed",
"event_id": "evt_g5h6i7j8k9l0m1n2",
"timestamp": "2025-01-28T10:16:20Z",
"api_version": "v1",
"data": {
"transaction": {
"id": "dt_12346",
"uuid": "660f9511-f39c-52e5-b827-557766551111",
"reference": "FLU-20250128-DEF456",
"partner_reference": "ORDER-67891",
"status": "failed",
"amount": 500.0,
"currency": "GHS",
"fee": 7.5,
"narration": "Payment for Order #67891",
"error_message": "Insufficient funds in customer account",
"bank_reference": "BNK-REF-789013",
"bank": {
"name": "Sample Bank",
"identifier": "SAM",
"country_code": "GH"
},
"customer": {
"name": "Ama Asante",
"phone_number": "+233247654321"
},
"created_at": "2025-01-28T10:15:50Z",
"processed_at": "2025-01-28T10:16:05Z",
"completed_at": null
},
"previous_status": "processing",
"metadata": {
"order_id": "67891",
"customer_email": "ama@example.com"
},
"error_details": {
"message": "Insufficient funds in customer account",
"code": "insufficient_funds"
}
}
}Common Error Codes
| Error Code | Description | Customer Action |
|---|---|---|
insufficient_funds | Not enough balance in account | Add funds and retry |
invalid_account | Account number or phone invalid | Verify account details |
transaction_declined | Customer declined USSD prompt | Retry transaction |
timeout | Request timed out | Retry transaction |
network_error | Network connectivity issue | Retry after some time |
unknown_error | Unspecified bank error | Contact support |
Handle Failures Gracefully
Always check for error_details in failed transactions and display user-friendly error messages. The raw error_message may contain technical details unsuitable for end users.
transaction.reversed
Description
Triggered when a previously completed transaction is reversed (refunded) by the bank or payment provider.
When Triggered
- Merchant initiates refund
- Bank reverses transaction due to error
- Dispute resolution requires reversal
- Regulatory/compliance requirement
Use Cases
- Reverse transaction in your system
- Credit customer account (for reversals)
- Send reversal notification
- Update order status to "refunded"
- Adjust accounting records
Example Payload
{
"event": "transaction.reversed",
"event_id": "evt_h6i7j8k9l0m1n2o3",
"timestamp": "2025-01-29T14:30:00Z",
"api_version": "v1",
"data": {
"transaction": {
"id": "dt_12345",
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"reference": "FLU-20250128-ABC123",
"partner_reference": "ORDER-67890",
"status": "reversed",
"amount": 100.0,
"currency": "GHS",
"fee": 1.5,
"narration": "Refund for Order #67890",
"bank_reference": "BNK-REF-789012",
"bank": {
"name": "Example Bank Ghana",
"identifier": "EXB",
"country_code": "GH"
},
"customer": {
"name": "Kwame Mensah",
"phone_number": "+233241234567"
},
"created_at": "2025-01-28T10:15:00Z",
"processed_at": "2025-01-28T10:15:12Z",
"completed_at": "2025-01-28T10:15:45Z"
},
"previous_status": "completed",
"metadata": {
"order_id": "67890",
"reversal_reason": "Customer requested refund",
"customer_email": "kwame@example.com"
}
}
}Reversal Metadata
Reversed transactions include a reversal_reason in metadata explaining why the reversal occurred.
Event Subscription
Default Subscription
By default, payment providers are subscribed to all transaction events. You'll receive webhooks for:
- ✅
transaction.created - ✅
transaction.pending - ✅
transaction.processing - ✅
transaction.completed - ✅
transaction.failed - ✅
transaction.reversed
Custom Subscriptions
To receive only specific events, contact your FLUID integration manager to configure selective event subscriptions.
Example: Minimal subscription (success/failure only)
✅ transaction.completed
✅ transaction.failed
❌ transaction.created (disabled)
❌ transaction.pending (disabled)
❌ transaction.processing (disabled)Event Dependencies
Some events are sequential. If you disable intermediate events (e.g., transaction.processing), you may miss important state transitions. We recommend keeping all events enabled unless you have specific performance or cost constraints.
Event Identification
Unique Event Identifiers
Each webhook includes multiple identifiers for tracking and deduplication:
{
"event": "transaction.completed", // Event type
"event_id": "evt_f4g5h6i7j8k9l0m1", // Unique event ID (per webhook)
"data": {
"transaction": {
"id": "dt_12345", // FLUID transaction ID
"uuid": "550e8400-...", // Universal UUID
"reference": "FLU-20250128-ABC123", // FLUID reference
"partner_reference": "ORDER-67890" // Your reference
}
}
}Deduplication Strategy
Use event_id or transaction.uuid for idempotency:
async function handleWebhook(payload) {
const eventId = payload.event_id;
// Check if we've already processed this event
const exists = await db.processedEvents.exists(eventId);
if (exists) {
console.log(`Event ${eventId} already processed, skipping`);
return { skipped: true };
}
// Process the event
await processTransaction(payload.data.transaction);
// Mark as processed
await db.processedEvents.insert({ eventId, processedAt: new Date() });
return { processed: true };
}Testing Events
Sandbox Environment
Test webhook events in the sandbox environment:
# Create a test transaction
curl https://sandbox-api.fluid-network.com/api/v1/payment-providers/debit-transactions \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+233241234567",
"bank_identifier": "ECO",
"amount": 10.00,
"currency": "GHS",
"narration": "Test webhook events",
"partner_reference": "test-001"
}'
# Expected webhooks received (in order):
# 1. transaction.created
# 2. transaction.pending
# 3. transaction.processing
# 4. transaction.completed (or transaction.failed)Mock Bank Responses
In sandbox, you can trigger specific outcomes using test phone numbers:
| Phone Number | Outcome | Events Triggered |
|---|---|---|
+233241234567 | Success | created → pending → processing → completed |
+233241111111 | Insufficient funds | created → pending → processing → failed |
+233242222222 | Timeout | created → pending → failed |
+233243333333 | Declined | created → pending → processing → failed |
Next Steps
See Also
- Webhooks Overview - Introduction to webhooks
- Error Handling Guide - Handle transaction failures
- API Reference - API endpoints