Case Study

How Shuttlers Uses hooksnode for Payment Callback Multiplexing Across Multiple Products

At a Glance

Company

Shuttlers

Industry

Mobility / Transportation

Use Case

Payment callback multiplexing

Payment Processor

Flutterwave

The Company

Shuttlers is a Nigerian mobility technology company that provides shared transportation solutions for corporate commuters. Over the years, Shuttlers has evolved from a single ride-booking product into a platform with multiple interconnected services — ride scheduling, subscription passes, wallet-based payments, and corporate billing.

The Challenge

Every Shuttlers product processes payments through Flutterwave. When a customer completes a payment — whether booking a ride, purchasing a monthly subscription pass, or topping up their wallet — Flutterwave sends a webhook callback to Shuttlers' infrastructure. Each product needed that callback to trigger multiple downstream actions:

  • Update the transaction status in the local database
  • Credit the customer wallet or activate the subscription
  • Notify the customer via email and SMS
  • Log the event to the analytics pipeline
  • Record revenue in the accounting system

Before hooksnode, each product team built their own webhook handling logic. This led to several problems:

  • Inconsistent reliability — Some products had retry logic, others didn't. Payment failures went undetected.
  • No shared observability — When a payment callback failed, each team had to dig through their own logs to understand why.
  • Duplicate infrastructure — Every product maintained its own webhook endpoint, Flutterwave webhook secret, and delivery monitoring.
  • No graceful isolation — When the analytics pipeline was slow, it blocked the customer notification from sending in some implementations.

The Solution: hooksnode as a Payment Webhook Multiplexer

Shuttlers deployed hooksnode as a centralized payment webhook ingestion layer. The architecture is straightforward:

  ┌────────────────────┐
  │                    │     ┌──────────────────────┐
  │  Flutterwave       │     │  Ride Service        │
  │  Payment           │     │  (mark trip as paid) │
  │  Callbacks         │     ├──────────────────────┤
  │                    │     │  Subscription Service │
  │  All products      │────►│  (activate pass)     │
  │  send to ONE URL   │     ├──────────────────────┤
  │                    │     │  Wallet Service       │
  │  /p/shuttlers      │     │  (credit balance)    │
  │                    │     ├──────────────────────┤
  │                    │     │  Notification Service │
  │                    │     │  (email + SMS)       │
  │                    │     ├──────────────────────┤
  │                    │     │  Analytics Pipeline   │
  │                    │     │  (PostHog + BigQuery)│
  │                    │     ├──────────────────────┤
  │                    │     │  Accounting Ledger   │
  │                    │     │  (record revenue)    │
  └────────────────────┘     └──────────────────────┘

Flutterwave sends all payment callbacks to a single hooksnode inbound URL. hooksnode fans out each callback to every downstream service concurrently, with per-destination filter rules, retry policies, and payload transformations.

How It Works in Practice

1. Single Ingestion Point

All Flutterwave webhooks are configured to POST to one URL: https://hooksnode.com/in/shuttlers. Whether it's a ride payment, a subscription renewal, or a wallet top-up, every callback arrives at the same endpoint. hooksnode persists the payload immediately before any processing — guaranteeing zero webhook loss.

2. Per-Destination Filter Rules

Not every service needs every callback. Shuttlers configured filter rules so each destination receives only relevant events:

Wallet Service → Filter: {"event_type": "wallet.topup"}
Subscription Service → Filter: {"event_type": "subscription.purchase"}
Ride Service → Filter: {"event_type": "ride.completed"}
Analytics → Filter: {"event_type": ["*"]} (all events)

3. Independent Retry Policies

Each destination has its own retry configuration. The notification service (which needs fast delivery) retries aggressively every minute for 15 minutes. The accounting ledger (less time-sensitive) retries every 15 minutes for 6 hours. This flexibility means every service gets the retry cadence that suits its requirements.

4. Payload Transformation per Service

Different downstream systems need different data shapes. Shuttlers uses hooksnode's Go text/template transformations to reshape the callback payload per destination:

// Notification service gets a simplified customer-facing format
{"customer": "{{.customer.email}}", "status": "{{.status}}", "amount": {{.amount}}}

// Accounting ledger gets the full transaction envelope
{"tx_id": "{{.id}}", "product": "{{.meta.product}}", "gross": {{.amount}}, "net": {{.meta.processor_fee}}}

5. Centralized Observability

Before hooksnode, debugging a payment failure meant checking each product's logs individually. Now, the Shuttlers team opens the hooksnode dashboard, finds the event, and sees the full delivery timeline — when it was received, which destinations it was sent to, whether each delivery succeeded or failed, and on which attempt. Failed events can be replayed with a single click.

Results

100%

Callback persistence rate (zero webhook loss since deployment)

1 URL

Replaced 5+ separate webhook endpoints across products

~15 min

Time to add a new downstream service to the fan-out

  • Unified event log — Every payment event across all products is visible in one dashboard.
  • Isolated failures — When the analytics pipeline is undergoing maintenance, ride payments still get processed and receipts still get sent.
  • Self-service onboarding — New products within Shuttlers add themselves as a hooksnode destination instead of building their own Flutterwave integration from scratch.

Key Takeaways

Shuttlers' experience demonstrates three principles for payment webhook infrastructure at scale:

  1. Centralize ingestion, distribute delivery — One endpoint for all payment callbacks simplifies configuration and ensures consistency, while per-destination queues isolate failures.
  2. Make retries a first-class concern — Payment callbacks are too important to trust to best-effort delivery. Exponential backoff with jitter and dead letter alerting ensures every event eventually arrives or triggers an alert.
  3. Observability is non-negotiable — When a payment goes missing, you need to know exactly where it stopped. A unified event timeline across all products is worth the investment.

Since deploying hooksnode, Shuttlers has expanded from 3 to 6 downstream services consuming payment callbacks — without changing the Flutterwave configuration once.

Build your own payment webhook infrastructure

hooksnode is free to start with 10,000 events per month. No credit card required.

Start free →