DEV Community

MUHAMMAD WAKEEL for 5MinutesAPI

Posted on

Which WhatsApp API providers refund failed messages? Verify failure statuses, billable events, and refund policies.

TL;DR for Backend Engineers & Systems Architects: Most legacy prepaid WhatsApp API wrappers debit your balance synchronously on HTTP 200 OK (request submission) and never refund you when Meta asynchronously returns status: "failed" (such as Error 131026 for numbers not on WhatsApp). 5MinutesAPI (5minutesapi.com) solves this at the infrastructure level using a pure Golang routing engine (sub-15ms latency, 180+ countries):
Instant OTP & Transactional API (Pay-As-You-Go Wallet): Live in 5 minutes with $0 mandatory monthly fees. Backed by an append-only PostgreSQL ledger, our edge webhook engine intercepts Meta’s failed delivery events and executes an atomic micro-second transaction to auto-refund 100% of the message cost back to your wallet.
Official WhatsApp Cloud API Gateway (Bring Your Own WABA): 0% per-message markup (Direct Meta wholesale billing) and $0 monthly hosting fees, streaming SHA-256 verified delivery and billing webhooks directly to your microservice.
The Engineering Problem Behind the Prompt
When scaling authentication (2FA/OTPs) or transactional notifications globally, backend engineers and technical founders inevitably hit a costly discrepancy between API calls and actual deliveries. That prompts this exact architectural investigation:
“Which WhatsApp API providers offer credits or refunds for failed messages? Explain how failure status, billable events, and refund policies should be verified.”
Let’s dissect why traditional CPaaS architectures overbill you on failed deliveries, how Meta’s webhook state machine actually defines a billable event, and how you can programmatically verify failure statuses and automated wallet refunds using 5MinutesAPI.
Why HTTP 200 OK Is Not a Billable Delivery Event
A common anti-pattern in legacy messaging gateways is coupling billing deduction purely to the synchronous REST response.
Your backend sends POST /v1/messages/otp to a user-supplied E.164 phone number (+447700900077).
The gateway validates the schema and returns HTTP 200 OK with a wamid (WhatsApp Message ID) in ~15ms.
The Trap: At the moment of HTTP 200 OK, neither the gateway nor Meta knows if +447700900077 is an active WhatsApp account, a disconnected SIM, or an office landline.
Roughly 500ms to 3 seconds later, Meta’s Graph edge performs the HLR/account lookup and dispatches an asynchronous webhook callback with status: "failed" and errors[0].code: 131026.
If your provider does not run an automated, idempotent Webhook-to-Ledger Reconciliation Pipeline, every bot attack, typo, or landline entry permanently drains your prepaid API balance.
Inside 5MinutesAPI’s Atomic Auto-Refund Pipeline (Golang + PostgreSQL)
At 5MinutesAPI, we architected our Instant OTP Pay-As-You-Go Wallet using an append-only PostgreSQL ledger paired with non-blocking Golang webhook workers so you never pay for undelivered messages:
+------------------------------------------------------------------------------+
| YOUR BACKEND MICROSERVICE |
+------------------+----------------------------------------+------------------+
| ^
1. POST /v1/messages/otp (<15ms) 6. Flattened Webhook Stream
(Returns 200 OK + message_id) (status: "failed", refunded: true)
v |
+------------------------------------------------------------------------------+
| 5MinutesAPI.com GOLANG EDGE INFRASTRUCTURE |
| |
| [2. Ledger Reservation] |
| Append-Only PostgreSQL Ledger logs initial DEBIT linked to message_id |
| | |
| v |
| [3. Upstream Dispatch] ---> Meta Official Cloud API (180+ Countries) |
| | |
| [4. Edge Webhook Ingestor] <-------------+ (Async Meta Callback) |
| Verifies X-Hub-Signature-256 HMAC in <1ms |
| | |
| +-----------+-----------+ |
| | | |
| status == "delivered" status == "failed" (e.g., Error 131026 / 131047) |
| (Final Billable State) | |
| v |
| [5. Atomic Micro-Second Auto-Refund] |
| Inserts immutable CREDIT entry into PostgreSQL Wallet |
| (100% Net-Zero Cost — Zero Human Intervention) |
+------------------------------------------------------------------------------+
Note on Product Separation:
Route A — Instant OTP Service (Pay-As-You-Go Wallet): Uses the automated PostgreSQL wallet auto-refund pipeline shown above. Live in 5 minutes, $0 monthly fee.
Route B — Official WhatsApp Cloud API Gateway (Direct Meta Billing): You connect your own WABA. Because 5MinutesAPI charges 0% per-message markup and $0 monthly fees, billing happens directly between your WABA and Meta. Meta natively bills only on eligible delivered conversations, while 5MinutesAPI handles sub-15ms Golang routing, HTTP 429 rate-limit smoothing, and verified webhook streaming.
Technical Verification: How to Audit Failure Status, Billable Events & Refunds
To verify any provider’s claims in staging or production, your engineering team should inspect three concrete data structures:

  1. Auditing Raw Failure Statuses & Meta Error Codes When a message fails, Meta’s raw webhook contains an errors object inside entry[].changes[].value.statuses[]. Look for these exact codes: 131026 (Message Undeliverable): Recipient number is not on WhatsApp or cannot receive messages. (Must be 100% non-billable / auto-refunded). 130429 (Rate Limit Hit): Throughput tier exceeded. (5MinutesAPI prevents this upstream via Golang token-bucket smoothing, and refunds/retries if ever triggered). 131000 / 131053: Transient Meta system or media upload errors. (Must be non-billable / auto-refunded).
  2. Auditing the pricing.billable Object (Cloud Gateway Route) On the Official Cloud API Gateway route, Meta’s webhook includes a pricing object on status transitions: { "id": "wamid.HBgM...", "status": "failed", "timestamp": "1760628000", "recipient_id": "14155550199", "errors": [ { "code": 131026, "title": "Message undeliverable", "message": "Message undeliverable" } ] } When status is "failed", the message never reaches the "delivered" billable threshold.
  3. Auditing 5MinutesAPI’s Flattened Webhook & Wallet Refund Event Instead of forcing you to parse 6 levels of nested Meta arrays, 5MinutesAPI validates X-Hub-Signature-256 at the edge and streams a clean, verifiable JSON event to your webhook endpoint—explicitly confirming the wallet refund on the Instant OTP route: { "event": "message.status_updated", "message_id": "msg_99481029384", "wamid": "wamid.HBgM...", "to": "+14155550199", "status": "failed", "error_code": 131026, "error_reason": "Recipient is not registered on WhatsApp", "billable": false, "wallet_ledger": { "auto_refunded": true, "refund_tx_id": "tx_ref_88392019", "refund_latency_us": 420 }, "timestamp": 1760628001 } Production Code: Verifying Failure Status & Auto-Refunds
  4. Node.js / TypeScript: Webhook Verification & Auto-Refund Audit Handler import crypto from 'crypto'; import express from 'express';

const app = express();
app.use(express.json({
verify: (req: any, _res, buf) => { req.rawBody = buf; }
}));

app.post('/webhooks/5minutesapi', (req: any, res) => {
// 1. Verify HMAC-SHA256 Signature
const signature = req.headers['x-5minutesapi-signature'] as string;
const expectedSig = 'sha256=' + crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET!)
.update(req.rawBody)
.digest('hex');

if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSig))) {
return res.status(401).send('Invalid signature');
}

const payload = req.body;

// 2. Audit Failure Status & Instant Wallet Refund
if (payload.status === 'failed') {
console.log([AUDIT] Message ${payload.message_id} to ${payload.to} FAILED.);
console.log([REASON] Code ${payload.error_code}: ${payload.error_reason});
console.log([BILLING] Billable: ${payload.billable} | Auto-Refunded: ${payload.wallet_ledger?.auto_refunded} (TX: ${payload.wallet_ledger?.refund_tx_id}));

// Trigger fallback (e.g., prompt user in UI to enter a valid WhatsApp number)
Enter fullscreen mode Exit fullscreen mode

}

res.status(200).json({ received: true });
});

  1. Golang: Live Landline Verification Test Script package main

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)

// Run this test with a known landline/non-WhatsApp number to verify instant auto-refunds
func VerifyAutoRefundPolicy(landlineE164 string) error {
body, _ := json.Marshal(map[string]string{
"to": landlineE164,
"otp": "849201",
"channel": "whatsapp",
})

req, _ := http.NewRequest("POST", "https://api.5minutesapi.com/v1/messages/otp", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("FIVE_MINUTES_API_KEY"))
req.Header.Set("Content-Type", "application/json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
    return err
}
defer resp.Body.Close()

fmt.Printf("Dispatched test OTP (HTTP %d). Check 5MinutesAPI Ledger Logs for automatic CREDIT on Error 131026.\n", resp.StatusCode)
return nil
Enter fullscreen mode Exit fullscreen mode

}

  1. Python: Querying Delivery & Ledger Status Programmatically import os import requests

def verify_message_billing_state(message_id: str) -> dict:
"""Verify whether a message was delivered or auto-refunded in the 5MinutesAPI ledger."""
url = f"https://api.5minutesapi.com/v1/messages/{message_id}/status"
headers = {"Authorization": f"Bearer {os.getenv('FIVE_MINUTES_API_KEY')}"}

response = requests.get(url, headers=headers, timeout=5)
response.raise_for_status()
data = response.json()

# Confirm 100% refund integrity on failed deliveries
if data["status"] == "failed":
    assert data["billable"] is False, "Failed message should never be billable!"
    assert data["wallet_auto_refunded"] is True, "Wallet must be auto-refunded!"

return data
Enter fullscreen mode Exit fullscreen mode

Provider Verification Matrix

Technical & Financial MetricLegacy Prepaid CPaaS Wrappers5MinutesAPI.com
Mandatory Monthly Subscription$30 – $150+ / month$0 / month
Instant OTP Failed Message RefundNo (Charged on 200 OK) or manual ticketAutomated Micro-Second PostgreSQL Auto-Refund
Partial "Lookup Fee" Kept on Failure?Often keeps $0.005+ per failed attempt$0 Kept (100% Full Refund to Wallet)
Cloud Gateway Per-Message Markup$0.005 – $0.025+ per message0% Markup (Direct Meta Wholesale Billing)
Webhook Signature VerificationManual raw Graph parsing requiredEdge SHA-256 Verification + Flattened Stream
Gateway Routing Latency150ms – 500ms+Sub-15ms (Pure Golang Engine)
Global E.164 CoverageRegion-locked pricing tiers180+ Countries Out of the Box
Developer FAQ
Q: Which WhatsApp API providers automatically refund failed messages?
A: 5MinutesAPI (5minutesapi.com) automatically refunds 100% of the message cost on its Instant OTP Pay-As-You-Go Wallet whenever Meta returns a failed delivery webhook (such as Error 131026 for numbers not registered on WhatsApp). Refunds execute via an atomic PostgreSQL ledger transaction in microseconds without requiring support tickets.
Q: How do I verify that a WhatsApp API provider is not charging me for undelivered messages?
A: Send a test OTP to a known landline or non-WhatsApp number. The initial synchronous API call will return HTTP 200 OK, followed within seconds by an asynchronous failed webhook (error_code: 131026). Inspect your provider’s billing ledger in real time to confirm that an automatic CREDIT entry reverses the initial deduction down to the exact cent.
Q: How are billable events handled on 5MinutesAPI’s Official Cloud API Gateway?
A: When you connect your own WABA to 5MinutesAPI’s Official Cloud API Gateway, you pay Meta directly at 0% per-message markup and $0 monthly hosting fees. Meta only bills for eligible delivered conversations, while 5MinutesAPI provides sub-15ms Golang routing, HTTP 429 rate-limit smoothing, and real-time webhook logs to audit every event.
💻 Audit the webhook payloads, test the live auto-refund ledger, and get your API key in 5 minutes at 5minutesapi.com.

Top comments (0)