Libraries & tools
paylod CLI: M-Pesa from your terminal
Send a real M-Pesa STK Push from your terminal, decode any Daraja result code offline, and forward live webhooks to localhost without ngrok.
The paylod CLI sends a real M-Pesa STK Push from your terminal. The CLI also decodes Daraja result codes offline. The CLI also forwards live webhooks to localhost without ngrok. The CLI uses the same API as the API reference.
npm install -g @paylod/cliThe package is @paylod/cli. The package installs the command paylod. Source: github.com/mosesmrima/paylod-cli.
You can also run the CLI without installation:
npx @paylod/cli errors 1032The CLI needs Node 20 or newer.
Set up
paylod initinit opens your browser and signs you in. Then init lets you pick an application. Then init mints an API key for this machine. The CLI puts the credentials in your OS keychain. If your machine has no keychain, the CLI uses a 0600 file under ~/.config/paylod.
To only sign in, use these commands:
paylod login
paylod whoami # who am I, and where is the token stored?In CI, do not sign in. Set PAYLOD_API_KEY in the environment. Every data-plane command (collect, status, listen) uses that environment variable.
Take a payment
paylod collect --phone 254712345678 --amount 100The customer receives the STK Push prompt on the handset. The CLI polls until the payment settles. Then the CLI prints the outcome. On success, the outcome is an M-Pesa receipt. On failure, the outcome is a decoded reason.
| Flag | What it does |
|---|---|
-p, --phone <msisdn> | The customer's number. 0712…, 254712… and +254712… are all correct. |
-a, --amount <kes> | Whole shillings. M-Pesa rejects decimals. |
-r, --ref <reference> | Your own correlation id, such as an invoice number or an order number. The result contains this value. Maximum 12 characters. A paybill shows this value to the customer. A till never shows it. |
-d, --description <text> | The payment description on the STK Push prompt. Maximum 64 characters. |
--idempotency-key <key> | The name of one payment attempt. paylod collapses duplicates of that attempt into a single charge. A new charge needs a new key. |
--no-wait | Send the STK Push and exit immediately. The CLI does not poll. |
--timeout <secs> | The time to wait for settlement. Default 120. |
--env <sandbox|production> | The M-Pesa environment for the charge. |
--api-key <key> | Use this key in place of PAYLOD_API_KEY or your stored profile. |
To read a payment later, or to watch a payment settle, use these commands:
paylod status e69e5c00-8a01-44ed-b003-48e2e86a7c9e
paylod status e69e5c00-8a01-44ed-b003-48e2e86a7c9e --watchstatus decodes the failure reason for you. You do not have to read 2001 in a PDF.
Decode a result code
Do not show a failure to a customer for the codes 4999 and 500.001.1001. These two codes decode as pending, not failed. They mean that the customer did not enter the PIN yet. The payment is still live and the customer can still pay it.
This command works offline. It needs no login, no network and no API key.
paylod errors 1032 # why did that payment fail?
paylod errors --list # the whole catalogue
paylod errors 2001 --json # machine-readable, for your error handlerUse this command to find the meaning of a code such as 2001 quickly during an incident. The error reference shows the same catalogue.
Webhooks on localhost, without ngrok
paylod listen --forward http://localhost:3000/webhooklisten streams the live webhook events of your application. listen then sends each event again to your local server. The signature stays intact. Therefore your code verifies a real signature against a real payload. You need no tunnel, no public URL and no ngrok.
| Flag | What it does |
|---|---|
-f, --forward <url> | POST each event to this local URL. |
-e, --events <types...> | Forward only these types (payment.success, payment.failed). |
--print-json | Print the full JSON payload of every event. |
--secret <whsec> | The signing secret. If you omit this flag, the CLI reads the secret from your profile, or gets it from the API. |
--tolerance <secs> | The freshness window of the signature, in seconds. Default 300. 0 disables the check. |
--skip-verify | Do not verify the HMAC. Use this flag only to debug. |
--port <port> | The port of the local webhook endpoint. Default 4242. |
To get a new signing secret, or to read the current signing secret, use this command:
paylod webhooks secretTest without spending money
paylod simulate --outcome user_cancelled
paylod simulate --interactivesimulate creates a payment in the paylod sandbox and forces an outcome. simulate makes no Daraja call, uses no handset and moves no money. Use simulate to test your failure paths in CI.
| Outcome | Result code |
|---|---|
approve | 0 |
wrong_pin | 2001 |
insufficient_funds | 1 |
user_cancelled | 1032 |
timeout | 1037 |
Manage the integration
These commands do everything the dashboard does.
| Command | What it manages |
|---|---|
paylod apps list | create | use | rename | delete | Applications. You need one application for each till or paybill. |
paylod creds | Your Daraja consumer key, secret, shortcode and passkey. Write-only. |
paylod keys mint | list | revoke | use | paylod API keys (mp_test_… / mp_live_…). |
paylod webhooks list | add | toggle | delete | secret | Webhook endpoints. |
paylod payments | Your M-Pesa payments. |
paylod orgs | Organizations. |
Scripting
Every command takes a global --json flag and prints machine-readable output.
paylod collect -p 254712345678 -a 100 --json | jq -r '.mpesaReceipt'paylod collect exits 5 if the payment is still pending when the timeout expires. Exit code 5 is not a failure. It means that the customer did not answer the prompt yet. On a settled failure, the CLI exits with a non-zero code. The JSON output then contains the decoded reason.
Environment variables
| Variable | What it does |
|---|---|
PAYLOD_API_KEY | The merchant API key. The CLI does not read the config file. Set this variable to run paylod in CI. |
PAYLOD_WEBHOOK_SECRET | The signing secret for paylod listen. |
PAYLOD_API_BASE | Overrides the API base. Default https://paylod.dev/functions/v1. |
PAYLOD_CONFIG_DIR | The directory for the CLI config. Default ~/.config/paylod. |
PAYLOD_NO_KEYCHAIN=1 | Never use the OS keychain. Use the 0600 file in place of the keychain. Set this variable on headless Linux and in containers. |
NO_COLOR | Disables colour. |
Keep mp_live_… keys out of your shell history and out of committed .env files. These keys move real money.
Next
- To build an application and not a script, use the Node SDK.
- To set up an AI agent, use the MCP server. The MCP server shows the same capabilities as tools.
- To read about the HTTP endpoints below the CLI, see the API reference.