Webhook Events: Handling Real-Time Payment Notifications
Table of Contents
Payments are inherently asynchronous. A card charge you initiate may succeed immediately — or it may pend, require 3DS authentication, trigger a fraud review, or result in a chargeback days later. If your application only reacts to the synchronous API response when you create a transaction, you will miss a large portion of payment lifecycle events that affect your business logic, customer experience, and financial reconciliation.
Webhooks are TIB Finance's mechanism for pushing real-time event notifications to your application the moment something significant happens. This guide covers everything you need to implement a robust, secure webhook handler. For broader API integration context, see the Payment API Integration Guide.
What Are Webhooks?
A webhook is an HTTP POST request sent by TIB Finance to a URL that you specify (your webhook endpoint) when a specific event occurs. Think of it as TIB Finance calling your application and saying "something just happened — here are the details."
The alternative — polling — involves your application repeatedly calling the TIB Finance API asking "did anything change?" Polling is inefficient, adds latency to your event processing, and creates unnecessary API load. Webhooks eliminate all three problems by delivering events at the moment they occur.
Setting Up Your Webhook Endpoint
Configure your webhook endpoint URL in the TIB Finance merchant dashboard under Settings > Webhooks. Your endpoint must:
- Be publicly accessible via HTTPS (not HTTP)
- Accept HTTP POST requests
- Return HTTP 200 (or any 2xx status) within 10 seconds
- Accept the
application/jsoncontent type
You can register multiple webhook endpoints and filter which event types each endpoint receives — for example, sending payment events to your order management system and dispute events to your finance team's system.
Event Types Reference
TIB Finance sends webhooks for the following event categories:
Payment Events
| Event Type | Description |
|---|---|
| payment.succeeded | A payment was successfully processed and funds will be captured. Trigger order fulfillment. |
| payment.failed | A payment attempt was declined or failed. Notify the customer to try a different card. |
| payment.pending | Payment is pending processing (e.g., ACH, bank transfer). Do not fulfill until payment.succeeded. |
| payment.captured | A previously authorized (auth-only) payment has been captured. |
| payment.cancelled | An authorized payment was cancelled before capture. |
Refund Events
| Event Type | Description |
|---|---|
| refund.created | A refund has been initiated. Update your records but wait for refund.succeeded. |
| refund.succeeded | Refund has been processed successfully and funds returned to the customer. |
| refund.failed | A refund failed to process. Manual intervention may be required. |
Dispute Events
| Event Type | Description |
|---|---|
| dispute.created | A chargeback or dispute has been filed. Respond within the deadline. |
| dispute.updated | A dispute's status has changed (e.g., evidence submitted). |
| dispute.closed | A dispute has been resolved. Check outcome field for won/lost. |
Webhook Payload Structure
All TIB Finance webhook payloads share a common envelope structure:
Always use the id field in the data.object to fetch the authoritative object from the API if you need complete, up-to-date details. Do not rely on cached data from earlier API calls.
Signature Verification
Every webhook request from TIB Finance includes a TIB-Signature HTTP header containing an HMAC-SHA256 signature of the request body, signed with your webhook secret. Always verify this signature before processing the event. Skipping signature verification exposes your application to replay attacks and spoofed events.
Security Critical
If you process a webhook without verifying the signature, an attacker could send a fake "payment.succeeded" event to your endpoint and trigger order fulfillment without any actual payment. Signature verification is non-negotiable.
Retry Logic
TIB Finance automatically retries webhook deliveries when your endpoint does not return a 2xx response. Understanding the retry schedule helps you design robust error handling:
- Immediate retry: If your endpoint returns a 5xx error or times out, TIB Finance retries after 30 seconds.
- Exponential backoff: Subsequent retries use exponential backoff: 1 minute, 5 minutes, 30 minutes, 2 hours, 8 hours, 24 hours.
- Maximum attempts: TIB Finance will attempt delivery up to 10 times over approximately 72 hours.
- Abandonment: After 10 failed attempts, the event is marked as failed. You can view and manually replay failed events from the merchant dashboard.
Design your webhook handler to return 200 immediately upon receipt, before doing any complex processing. Acknowledge receipt first, then process asynchronously using a queue or background job. This prevents timeouts that cause unnecessary retries.
Idempotency
Due to the retry mechanism, your webhook handler must be idempotent — processing the same event multiple times must produce the same result as processing it once. Without idempotency, retried events can cause duplicate order fulfillments, duplicate email sends, or incorrect financial records.
Implement idempotency by tracking processed event IDs:
Best Practices
A summary of key recommendations for a production-grade webhook implementation:
- Always verify signatures. Reject any webhook that fails signature verification with HTTP 401.
- Respond within 10 seconds. Acknowledge first, process asynchronously using a job queue.
- Implement idempotency. Store processed event IDs and skip duplicates.
- Use HTTPS only. Never configure a webhook endpoint on an HTTP URL.
- Fetch fresh data from the API. If you need complete object details, fetch them via API using the object ID in the event rather than trusting only the webhook payload.
- Monitor for failures. Set up alerting for failed webhook deliveries, especially for critical events like payment.succeeded and dispute.created.
- Test in the sandbox. The TIB Finance sandbox allows you to manually trigger any event type to test your handler. See the sandbox testing guide.
- Handle all event types gracefully. Your handler will receive event types you may not have explicitly handled. Always have a default case that returns 200 to prevent unnecessary retries for events you intentionally ignore.
- Log everything. Log the raw payload, signature verification result, and your processing outcome for every webhook received. This is essential for debugging and financial reconciliation.
- Use separate endpoints per environment. Never send production webhooks to a development or staging endpoint, and vice versa.