paylod
CLI

Libraries & tools

paylod CLI: M-Pesa from your terminal

.md

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.

Install
npm install -g @paylod/cli

The 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
npx @paylod/cli errors 1032

The CLI needs Node 20 or newer.

Set up

Terminal
paylod init

init 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:

Terminal
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

Terminal
paylod collect --phone 254712345678 --amount 100

The 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.

FlagWhat 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-waitSend 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:

Terminal
paylod status e69e5c00-8a01-44ed-b003-48e2e86a7c9e
paylod status e69e5c00-8a01-44ed-b003-48e2e86a7c9e --watch

status 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.

Terminal
paylod errors 1032          # why did that payment fail?
paylod errors --list        # the whole catalogue
paylod errors 2001 --json   # machine-readable, for your error handler

Use 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

Terminal
paylod listen --forward http://localhost:3000/webhook

listen 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.

FlagWhat it does
-f, --forward <url>POST each event to this local URL.
-e, --events <types...>Forward only these types (payment.success, payment.failed).
--print-jsonPrint 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-verifyDo 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:

Terminal
paylod webhooks secret

Test without spending money

Terminal
paylod simulate --outcome user_cancelled
paylod simulate --interactive

simulate 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.

OutcomeResult code
approve0
wrong_pin2001
insufficient_funds1
user_cancelled1032
timeout1037

Manage the integration

These commands do everything the dashboard does.

CommandWhat it manages
paylod apps list | create | use | rename | deleteApplications. You need one application for each till or paybill.
paylod credsYour Daraja consumer key, secret, shortcode and passkey. Write-only.
paylod keys mint | list | revoke | usepaylod API keys (mp_test_… / mp_live_…).
paylod webhooks list | add | toggle | delete | secretWebhook endpoints.
paylod paymentsYour M-Pesa payments.
paylod orgsOrganizations.

Scripting

Every command takes a global --json flag and prints machine-readable output.

Terminal
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

VariableWhat it does
PAYLOD_API_KEYThe merchant API key. The CLI does not read the config file. Set this variable to run paylod in CI.
PAYLOD_WEBHOOK_SECRETThe signing secret for paylod listen.
PAYLOD_API_BASEOverrides the API base. Default https://paylod.dev/functions/v1.
PAYLOD_CONFIG_DIRThe directory for the CLI config. Default ~/.config/paylod.
PAYLOD_NO_KEYCHAIN=1Never use the OS keychain. Use the 0600 file in place of the keychain. Set this variable on headless Linux and in containers.
NO_COLORDisables 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.