Skip to main content

Who this guide is for

Use this guide if you are an aggregator or a high-volume merchant that needs:
  • Dedicated M-Pesa shortcode routing
  • Sub-merchant level transaction attribution
  • Advanced payout routing controls
If you do not need dedicated shortcode routing or sub-merchant attribution, use the standard endpoint payloads and only send required fields.

Integration paths

PathBest forPayload style
Standard merchant pathMost merchantsRequired fields only
Enterprise pathAggregators and large merchantsRequired + enterprise fields

Enterprise-only fields by endpoint

The table below lists fields marked with the ENTERPRISE badge in the API reference.
EndpointFieldNotes
POST /v1/mpesa/chargeshortcode ENTERPRISERoute via your dedicated collections shortcode
POST /v1/mpesa/chargesubMerchantId ENTERPRISEAuto-created on first use if missing; blocked only when suspended
POST /v1/mpesa/chargemetadata.subMerchantDetails ENTERPRISEOptional enrichment details for first-time auto-create
POST /v1/mpesa/b2cshortcode ENTERPRISERoute via your dedicated payouts shortcode
POST /v1/mpesa/b2csubMerchantId ENTERPRISEAuto-created on first use if missing; blocked only when suspended
POST /v1/mpesa/b2cmetadata.subMerchantDetails ENTERPRISEOptional enrichment details for first-time auto-create
POST /v1/mpesa/b2bshortcode ENTERPRISERoute via your dedicated payouts shortcode
POST /v1/mpesa/b2bsubMerchantId ENTERPRISEAuto-created on first use if missing; blocked only when suspended
POST /v1/mpesa/b2bmetadata.subMerchantDetails ENTERPRISEOptional enrichment details for first-time auto-create
Do not send enterprise-only fields unless your integration requires them. Over-specifying optional fields is a common source of integration errors.

End-to-end enterprise setup

1

Provision dedicated shortcodes

Work with Fingo to provision dedicated shortcode setup for your organization.
  • Collections traffic is routed through your collections shortcode.
  • Payout traffic is routed through your payouts shortcode.
2

Set up sub-merchants (if applicable)

You can pass subMerchantId directly in requests.
  • If the ID does not exist yet for your organization, Fingo auto-creates it in active state.
  • If the ID exists and is suspended, the request is rejected.
  • You can pass metadata.subMerchantDetails to enrich first-time auto-created records.
Use your own internal sub-merchant identifiers consistently in requests.
3

Start with minimal payloads

Go live first with required fields only, then add enterprise-only fields where you need deterministic routing.
4

Add enterprise routing fields intentionally

Add shortcode and subMerchantId only on flows that require them.
Apply enterprise fields per transaction type, not globally across all requests.
5

Verify webhook payloads and reconciliation

Verify webhook signatures, reconcile by merchantTransactionId and transactionId, and monitor failure reasons for optional-field misuse.

Request patterns

C2B charge

curl -X POST "https://api.fingopay.io/v1/mpesa/charge" \
  -H "Authorization: Bearer $FINGO_API_KEY" \
  -H "Idempotency-Key: 8b47872a-4de9-4c13-b73a-19803f55b1e4" \
  -H "Content-Type: application/json" \
  -d '{
    "merchantTransactionId": "invoice_48291",
    "amount": 150000,
    "phoneNumber": "+254712345678",
    "narration": "Invoice 48291"
  }'

B2C payout

curl -X POST "https://api.fingopay.io/v1/mpesa/b2c" \
  -H "Authorization: Bearer $FINGO_API_KEY" \
  -H "Idempotency-Key: 2d95d474-2ef8-4446-b9cb-5d8b3401434d" \
  -H "Content-Type: application/json" \
  -d '{
    "merchantTransactionId": "payout_97233",
    "amount": 420000,
    "phoneNumber": "+254701234567",
    "narration": "Salary payout"
  }'

B2B transfer

curl -X POST "https://api.fingopay.io/v1/mpesa/b2b" \
  -H "Authorization: Bearer $FINGO_API_KEY" \
  -H "Idempotency-Key: 5a101014-d59d-4d0b-a9a8-fd3092ab28f3" \
  -H "Content-Type: application/json" \
  -d '{
    "merchantTransactionId": "b2b_4521",
    "amount": 2500000,
    "accountNumber": "1234567",
    "accountNumberType": "paybill",
    "beneficiary": "INV-12345",
    "narration": "Restock float"
  }'

Common mistakes to avoid

  • Sending dedicated shortcode values that do not belong to your organization
  • Reusing idempotency keys with different request bodies
  • Including optional routing fields in all requests by default

Next steps