Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.moflay.com/llms.txt

Use this file to discover all available pages before exploring further.

Use the REST API when your backend is not running Node.js or when you want direct control over HTTP requests.

Prerequisites

Sandbox test values

For the default sandbox path, you do not need to set up Daraja credentials before your first payment. Moflay uses default sandbox test credentials unless you add your own sandbox credentials. Use these values for the first test:
ValueUse
254712345678Default sandbox test phone number
amount: 1000KES 10.00 in minor currency units
mof_test_...Sandbox API key
Sandbox payments do not move real money. The first response commonly returns pending; check the final status by polling during development or by using webhooks in production.

Send your first payment

1

Store your API key

export MOFLAY_API_KEY="mof_test_your_api_key"
2

Start an express payment

Call POST /v1/express with either phoneNumber or customerId. For the first test, use phoneNumber.
curl https://api.moflay.com/v1/express \
  -X POST \
  -H "Authorization: Bearer $MOFLAY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1001" \
  -d '{
    "phoneNumber": "254712345678",
    "amount": 1000,
    "description": "Order 1001",
    "accountReference": "ORDER1001"
  }'
The API returns 202 Accepted after Moflay sends the payment request to M-Pesa.
{
  "paymentId": "pay_ABC123DEF456GHI",
  "transactionId": "trxn_ABC123DEF456GHI",
  "customerId": "cus_GqfKXLmg61LURZhB",
  "phoneNumber": "254712345678",
  "amount": 1000,
  "currency": "KES",
  "status": "pending",
  "description": "Order 1001",
  "accountReference": "ORDER1001",
  "environment": "sandbox",
  "timestamp": "2024-12-19T10:25:00.000Z",
  "message": "Payment request sent to customer"
}
3

Check the payment status

Use the paymentId returned by POST /v1/express to read the latest payment status. You can also use the related transactionId if that is the identifier you stored.
curl https://api.moflay.com/v1/payments/pay_ABC123DEF456GHI \
  -H "Authorization: Bearer $MOFLAY_API_KEY"
curl https://api.moflay.com/v1/payments/trxn_ABC123DEF456GHI \
  -H "Authorization: Bearer $MOFLAY_API_KEY"
The status can move from pending to a final state such as completed, failed, or canceled. See Transaction statuses for the full status reference.

Request rules

FieldRequirement
phoneNumber or customerIdOne is required
amountInteger in minor currency units, greater than 0, up to 250000
descriptionRequired, up to 13 characters
accountReferenceOptional, up to 12 alphanumeric characters
Idempotency-KeyOptional, recommended for payment creation retries
If you use customerId, do not send extra customer fields such as customerName or customerDescription in the same request.

Production status handling

Polling GET /v1/payments/{id} is useful during development. In production, configure Moflay webhooks so your backend receives signed payment events such as payment.completed, payment.failed, and payment.canceled.

Verify the result

Your HTTP integration is working when:
  • POST /v1/express returns 202
  • The response includes a paymentId
  • GET /v1/payments/{id} returns the same payment in the sandbox environment

Troubleshooting

  • Payment creation returns invalid_access: Add the express.pay permission to the key or create a new sandbox key with that permission.
  • Status polling returns invalid_access: Add the transactions.read permission to the key or create a new sandbox key with that permission.
  • The payment does not appear in the dashboard: Confirm you are viewing the sandbox environment.