E-commerce11 min read

Wave webhooks: idempotency, signature and security (Senegal 2026)

Mohamed Bah·Fondateur, Kolonell
June 27, 2026
Share:
Wave webhooks: idempotency, signature and security (Senegal 2026)

Wave webhooks: idempotency, signature and security (Senegal 2026)

E-commerce

The verdict in three sentences

The webhook is the only source of truth for a Wave payment: never validate an order on the browser return, always on the server event. Three mechanisms make it reliable: verifying the HMAC signature to authenticate Wave, an idempotency table indexed on event_id to process each event only once, and responding 200 immediately (< 10 s) then processing in a queue. Without these three pillars, you risk double-credits, fake confirmations and ghost orders.

The Wave webhook events to handle

Wave sends several event types; your handler must route them cleanly. 2026 orders of magnitude (estimate, check the Wave Business docs):

EventStatusRecommended action
checkout.session.completedcompletedValidate order, release delivery
checkout.session.failedfailedNotify customer, offer another wallet
checkout.session.processingprocessingWait, release nothing
refund.completedrefundedCancel order, update stock
refund.failedfailedAlert support
balance.payoutsettledMark T+1 settlement received

Signature, idempotency and retries

Wave signs each payload (HMAC) and retries on failure. 2026 reference parameters:

MechanismReference valueWhy
Signature algorithmHMAC-SHA256Authenticate Wave origin
Signature headerWave-SignatureCompare to local computation
Retry count5 attempts over 24 hTolerate a temporary outage
BackoffExponential (1m, 5m, 30m, 2h, 6h)Avoid hammering
Expected timeout10 s maxBeyond this, Wave assumes failure
Expected responseFast HTTP 200Confirms receipt

The idempotency table stores each event_id with a uniqueness constraint: if the event arrives twice (retry after timeout), the insert fails and processing is skipped — the credit happens only once.

A robust Next.js handler

`ts

export async function POST(req: Request) {

const raw = await req.text();

const sig = req.headers.get("Wave-Signature");

if (!verifyHmac(raw, sig, process.env.WAVE_SECRET))

return new Response("invalid signature", { status: 401 });

const event = JSON.parse(raw);

const inserted = await db.insertIfAbsent("wave_events", event.id);

Need a professional website?

Kolonell builds websites that attract clients, optimized for the Sénégalese market. Free quote in 2 minutes.

// Respond 200 right away, then process in a queue

if (inserted) await queue.enqueue("wave", event);

return new Response("ok", { status: 200 });

}

`

The handler does three things and returns: verify the signature, deduplicate via insertIfAbsent, respond 200. All business logic (order validation, email, stock) goes to an async queue to stay under 10 s.

Mini case study

Ibrahim, a restaurateur in Dakar with delivery, was getting 2 % of orders paid but never confirmed because his handler validated on the browser return — cut off when the customer closed the app. On 1,500 orders/month at 6,500 FCFA, that meant 30 lost orders, i.e. 195,000 FCFA/month in disputes and manual refunds. After switching to a signed + idempotent webhook, the confirmation rate rose to 99.7 % and disputes nearly vanished.

FAQ

Why respond 200 before processing?

If your processing exceeds 10 s, Wave treats the delivery as failed and triggers a retry, creating duplicates. Responding 200 fast then queuing breaks that loop.

What if the signature doesn't match?

Return a 401 and process nothing: an improperly signed payload is not authenticated and could be a fraud attempt.

How long does Wave retry?

Generally 5 attempts spread over 24 h with exponential backoff (2026 estimate). Your idempotency table ensures none of these retries double-credit.

Should I store every event?

Yes, at minimum the event_id, status and timestamp. It's essential for accounting reconciliation and for replaying an event after a bug.

Let's talk about your project. We deliver signed, idempotent and monitored Wave webhooks, production-ready. WhatsApp +221 77 596 93 33.

Tags:#wave#webhook#idempotence#securite#api#nextjs#senegal#2026
Share:

Mohamed Bah

Fondateur, Kolonell

Passionate about digital and entrepreneurship in Africa, Mohamed has been helping Sénégalese businesses with their digital transformation since 2020. Founder of Kolonell, he believes every SME deserves a professional and accessible online présence.