Skip to content
HomeAbout MeMy WorkServicesBlogContact
Back to Blog
M-PesaMarch 30, 20268 min read

How I Fixed M-Pesa Daraja API Error 404.001.03 on B2B — It Wasn’t My Code

If you’ve just gone live with your M-Pesa Daraja integration and your B2B or B2C requests are returning this:

{
"requestId": "xxxx-xxxx-xxxx",
"errorCode": "404.001.03",
"errorMessage": "Invalid Access Token"
}

Stop debugging your code. I spent hours going down that rabbit hole while building the payment integration for PropFlow, a property management SaaS that collects rent via M-Pesa for Kenyan landlords. Everything worked perfectly in sandbox. STK Push? Flawless. C2B callbacks? Coming through. Then I tried to add B2B payments in production so landlords could receive disbursements, and I hit 404.001.03 on every single request.

Here’s what was actually wrong, and how I fixed it.


The Real Problem: B2B and B2C Are Not Enabled by Default

This is the thing nobody tells you clearly in the Daraja documentation.

When you create a production app on the Daraja portal and go live, your app gets approved for the APIs you selected during the go-live process, typically STK Push (Lipa Na M-Pesa Online) and C2B. But B2B and B2C are not automatically enabled on your shortcode. They require separate whitelisting by Safaricom.

So your access token is valid. Your credentials are correct. Your code is fine. The API is simply rejecting your requests because your shortcode hasn’t been authorized to make B2B or B2C calls. Safaricom returns 404.001.03 instead of a more descriptive error, which is what makes this so confusing.


What I Tried First (And Why It Didn’t Help)

Before I figured out the actual issue, I went through the usual debugging checklist:

Checked the HTTP method for token generation. The OAuth endpoint requires GET, not POST. Mine was already correct.

Verified I was using production credentials. Consumer Key, Consumer Secret, and Passkey were all from the production app. Base URL was https://api.safaricom.co.ke. All good.

Regenerated the SecurityCredential. For B2B, you need to encrypt the initiator password using Safaricom’s production certificate (not the sandbox one). I downloaded a fresh certificate from the Daraja portal and re-encrypted. Still 404.001.03.

Checked token expiry. Daraja tokens expire after 3600 seconds. I was generating a fresh one before each request. Not the issue.

Tried different CommandIDs. BusinessPayBill, BusinessPayToBulk, MerchantToMerchantTransfer. All returned the same error.

None of this worked because the problem wasn't in my code at all.


The Fix: Contact Safaricom to Whitelist B2B/B2C on Your Shortcode

The solution is straightforward once you know what’s happening. You need to contact Safaricom’s API support team and request them to enable B2B (and/or B2C) on your production shortcode.

Here’s who to contact:

Email: apisupport@safaricom.co.ke

You can also try:

  • m-pesabusiness@safaricom.co.ke

Phone: Call 2222 on your Safaricom line (this is the M-Pesa Business support line).

When you reach out, include the following in your email:

In my case, I called 2222 and explained the situation. Once they enabled B2B on my shortcode, the exact same code that was failing started working immediately. No code changes needed.


Why This Happens

When you go through the “Go Live” process on the Daraja portal, you select the API products you want to use. However, certain APIs require additional verification and manual activation on Safaricom’s end:

  • STK Push (Lipa Na M-Pesa Online): Usually activated automatically during go-live
  • C2B (Customer to Business): Usually activated automatically
  • B2C (Business to Customer): Requires separate whitelisting
  • B2B (Business to Business): Requires separate whitelisting
  • Account Balance and Transaction Status: May also require activation

The Daraja portal doesn’t make this distinction obvious. You can create an app with B2B selected, go live, and still not have B2B access. The portal won’t warn you. Your first clue will be 404.001.03 in production.

Also worth noting: you cannot use the same shortcode for both C2B and B2C in some configurations. If your shortcode was approved for C2B/STK Push, you may need a separate shortcode for B2C, or you need Safaricom to explicitly add B2C permissions to your existing one. Clarify this with the support team when you call.


Quick Diagnostic: Is This Your Issue?

Before calling Safaricom, verify this is actually a whitelisting problem and not something else:

Yes, it’s probably whitelisting if:

  • Your STK Push and/or C2B work fine in production
  • Only B2B or B2C calls return 404.001.03
  • The same B2B/B2C code works in sandbox
  • You’ve verified your token, credentials, and certificate are all production

No, check other causes if:

  • All API calls fail, including STK Push (likely a credentials issue)
  • You get 404.001.03 on the token generation call itself (likely using POST instead of GET)
  • You’re still pointing to sandbox URLs

Lessons Learned

Three things I took away from this experience:

First, the error message is misleading. “Invalid Access Token” suggests an authentication problem. In reality, your token is valid but your shortcode isn’t authorized for that specific API. Safaricom should return a more descriptive error, but they don’t. Don’t waste hours debugging authentication when the issue is authorization.

Second, always test B2B and B2C immediately after going live. Don’t wait until you’ve built out your entire disbursement flow to discover it doesn’t work. The moment you get production credentials, make a test B2B or B2C call. If it fails with 404.001.03, call Safaricom right away because the whitelisting process can take a few hours to a couple of days.

Third, keep Safaricom API support on speed dial. Daraja is powerful but the documentation has gaps. The support team at apisupport@safaricom.co.ke is your best resource. Be specific in your emails, include your shortcode and app details, and follow up if you don't hear back within 24 hours.


Boniface Muchendu

Boniface Muchendu

Full-stack developer based in Nairobi. I build software for African businesses and have integrated M-Pesa’s Daraja API in production across multiple applications, including PropFlow and DukaSale.

Need help with M-Pesa integration?

I’ve been through the pain so you don’t have to.

Get in touch →