</>CodeWithKarani
All topics
Topic

APIs & Integrations

22 articles in this topic.

Security9 min read

Blocked by CORS Policy: Stop Reaching for Access-Control-Allow-Origin: *

The wildcard breaks the moment you send cookies, and reflecting the Origin header is worse. Here is the allowlist pattern, the nginx config and the curl test that proves it.

Read
Payments & Fintech7 min read

Daraja invalid access token: 401.003.01 is not 404.001.03

Two Daraja errors say 'Invalid Access Token' and mean different things. One is a wrong-environment token you can fix in code, the other is an entitlement problem only Safaricom can fix.

Read
Payments & Fintech8 min read

Daraja Returns 429 With a Body Your Error Parser Cannot Read

An HTTP 429 from M-Pesa Daraja is an Apigee spike arrest fault, not Daraja JSON, so most error handlers log undefined and swallow it. Here is how to classify, pace and back off.

Read
Payments & Fintech7 min read

M-Pesa C2B Sandbox Callbacks Only Fire Half the Time

Daraja's C2B sandbox drops most confirmation callbacks, so developers debug ngrok and nginx for days. Here is why it happens and the deploy-first workflow that replaces it.

Read
Payments & Fintech7 min read

M-Pesa 'Unable to Send STK Prompt' (1025/9999): Check the Length

Daraja returns 1025 for both a too-long TransactionDesc and a genuine M-Pesa outage. One retries successfully, the other never will. Here is how to tell them apart.

Read
Payments & Fintech8 min read

M-Pesa error 2001 invalid initiator: the stale certificate trap

M-Pesa B2C returns ResultCode 2001, 'The initiator information is invalid.' It is rarely the initiator name. It is usually a certificate copied from the wrong place.

Read
Payments & Fintech9 min read

M-Pesa Daraja 500.001.1001 when your consumer key is actually correct

Daraja's 'Wrong credentials' error hides two unrelated causes, and neither is your API key. Usually it is a timestamp generated twice that drifts by one second.

Read
Payments & Fintech9 min read

M-Pesa ResultCode 4999 Is Not a Failure: Handling Undocumented Daraja Codes

Daraja's STK query can return 4999, which no Safaricom document defines. Treating it as failed causes double charges. Here is the three-bucket model that prevents it.

Read
Payments & Fintech9 min read

M-Pesa Invalid Access Token After Go-Live: It Is Not Your OAuth Code

Daraja returns 404.001.03 Invalid Access Token when your shortcode is not whitelisted, not just when the token is bad. One curl tells you which, and saves two days.

Read
Security8 min read

Your Webhook Endpoint Trusts Anyone Who Can curl It

Skipping HMAC verification turns a webhook into an unauthenticated database write. Why verification breaks when you finally add it, and the raw-body fix for Stripe, GitHub and Shopify.

Read
Payments & Fintech9 min read

Daraja 404.001.03: Cache the Access Token, Don't Mint a New One

M-Pesa Daraja tokens live about an hour. Fetching one per request gets you throttled; caching forever gets you 404.001.03. The proactive refresh pattern Safaricom never documents.

Read
Frappe/ERPNext8 min read

Reverse-Engineering the Frappe REST API: the Reference Nobody Wrote

Frappe auto-generates a REST API from your DocTypes but ships no OpenAPI spec, so integrations are trial and error. Here is the working reference: filters, fields, auth, child tables and the gotchas.

Read
Payments & Fintech9 min read

M-Pesa error 1037: the STK push that never reached the phone

Daraja 1037 is not a declined payment. It means the handset never answered the SIM toolkit prompt. How to classify it, poll for it, and retry without creating duplicate orders.

Read
Payments & Fintech8 min read

M-Pesa 1019 vs 1037 vs 1032: three STK failures that look identical and are not

1019 means the prompt arrived and the user was too slow. 1037 means it never arrived. 1032 means they cancelled. Conflating them hides whether your problem is network, copy or timeout.

Read
APIs & Integrations8 min read

Webhook Signature Verification Fails Randomly? It Is Your Body Parser Order

A webhook signature check that passes on some events and fails on others is not a secret problem. Why re-serialized JSON breaks the HMAC, and how to verify the raw body before parsing.

Read
APIs & Integrations8 min read

Your Queue Isn't Broken: Background Jobs Need Idempotency, Not Exactly-Once

A crashed worker charged the card twice. The queue did its job: at-least-once delivery. The real fix is an idempotent handler, not exactly-once infrastructure.

Read
Security7 min read

A Valid JWT Signature Isn't Enough: Check the aud and iss Claims

A valid JWT signature proves who issued the token, not who it was for. Without aud and iss checks, one service's token works against another. Here is the fix.

Read
Payments & Fintech7 min read

Your M-Pesa Integration Needs Nightly Reconciliation, Not Just Callbacks

A missing M-Pesa callback is not a failed payment, it is an unknown outcome. Build a scheduled Transaction Status reconciliation job so lost callbacks never strand a paid order.

Read
Payments & Fintech8 min read

M-Pesa STK Push Callback Never Arrives? Reconcile With the Transaction Status Query API

STK Push callbacks are not guaranteed even with a perfect URL. Build a reconciliation job that treats the Transaction Status Query API as the real source of truth.

Read
Payments & Fintech7 min read

Payment Webhook Signature Fails on One Server: The Clock-Drift Check Nobody Runs

Stripe webhook verification fails on one box but not the others? Its signature is time-bound and your clock drifted. Why Paystack and Flutterwave are immune, and the NTP fix.

Read
Payments & Fintech8 min read

When the Webhook Succeeds but Your Database Write Doesn't: Handling Orphaned Payments

The provider took the money, your write crashed, and now you have a payment with no order. Why try/catch cannot fix it, and the idempotency, outbox and reconciliation design that can.

Read
APIs & Integrations7 min read

The Webhook That Charged a Customer Twice: Timeout-Induced Duplicate Processing

A webhook that works perfectly in dev quietly double-charges a real customer in production. Here is why the provider retries, and how to make your handler idempotent.

Read