Skip to main content
Waftpay provides two environments:
  • Sandbox — a safe, isolated environment for development and QA.
  • Production — live traffic and real money movement.
Functionality and payload shapes are parity-aligned between environments. Any differences are noted below.

Base URLs

Use the correct host per environment when composing endpoints.
EnvironmentBase URL
Sandboxhttps://sandbox.waftpay.io/api
Productionhttps://api.waftpay.io
Note: In Sandbox, endpoints are prefixed with /api. In Production, the /api prefix is not used.

Service examples

Authentication (Consumer credentials):
  • Sandbox: https://sandbox.waftpay.io/api/authentication-service/v1/api/generate-token
  • Production: https://api.waftpay.io/authentication-service/v1/api/generate-token
Payments / Payouts:
  • Sandbox: https://sandbox.waftpay.io/api/payments-api-service/v1/payouts
  • Production: https://api.waftpay.io/payments-api-service/v1/payouts

Switching environments

We recommend parameterizing the base URL and credentials.
# .env (example)
WAFTPAY_BASE_URL=https://sandbox.waftpay.io/api
WAFTPAY_CONSUMER_KEY=...
WAFTPAY_CONSUMER_SECRET=...
WAFTPAY_PUBLIC_KEY_PATH=./keys/sandbox_public.pem
WAFTPAY_PRIVATE_KEY_PATH=./keys/sandbox_private.pem
// config.ts
export const WAFTPAY = {
  baseUrl: process.env.WAFTPAY_BASE_URL ?? "https://sandbox.waftpay.io/api",
  consumerKey: process.env.WAFTPAY_CONSUMER_KEY!,
  consumerSecret: process.env.WAFTPAY_CONSUMER_SECRET!,
};
Switch to Production by setting:
WAFTPAY_BASE_URL=https://api.waftpay.io
# ...and production credentials / keys

Quick start: per‑environment calls

1) Get an access token

# SANDBOX
curl -X POST \
  https://sandbox.waftpay.io/api/authentication-service/v1/api/generate-token \
  -H 'Content-Type: application/json' \
  -d '{
    "consumer_key":"<sandbox-consumer-key>",
    "consumer_secret":"<sandbox-consumer-secret>"
  }'
# PRODUCTION
curl -X POST \
  https://api.waftpay.io/authentication-service/v1/api/generate-token \
  -H 'Content-Type: application/json' \
  -d '{
    "consumer_key":"<prod-consumer-key>",
    "consumer_secret":"<prod-consumer-secret>"
  }'

2) Create a payout

# SANDBOX
curl --request POST \
  --url https://sandbox.waftpay.io/api/payments-api-service/v1/payouts \
  --header 'Authorization: Bearer <sandbox-access-token>' \
  --header 'Content-Type: application/json' \
  --header 'X-Custom-Signature: <signature>' \
  --data '{
  "transaction": {
    "reference": "TXN213687756272200",
    "amount": 1000,
    "currency": "KES",
    "description": "Test description",
    "service_code": "MPESAB2C",
    "timestamp": "2025-01-21T12:30:10Z"
  },
  "originator": {
    "msisdn": "254708374149",
    "channel": "USSD",
    "country": "KE"
  },
  "recipient": {
    "reference": "INVJMA02",
    "account": "254708374149"
  },
  "callback_url": "https://staging.example.com/waftpay/callbacks"
}'
# PRODUCTION
curl --request POST \
  --url https://api.waftpay.io/payments-api-service/v1/payouts \
  --header 'Authorization: Bearer <prod-access-token>' \
  --header 'Content-Type: application/json' \
  --header 'X-Custom-Signature: <signature>' \
  --data '{
  "transaction": {
    "reference": "TXN213687756272201",
    "amount": 1000,
    "currency": "KES",
    "description": "Live payout",
    "service_code": "MPESAB2C",
    "timestamp": "2025-01-21T12:30:10Z"
  },
  "originator": {
    "msisdn": "2547XXXXXXXX",
    "channel": "USSD",
    "country": "KE"
  },
  "recipient": {
    "reference": "INVLIVE01",
    "account": "2547YYYYYYYY"
  },
  "callback_url": "https://merchant.example.com/waftpay/callbacks"
}'

Credentials & keys

  • Maintain separate consumer keys/secrets and signing keys per environment.
  • Keep private keys server‑side only and rotate regularly.
  • Enforce least privilege: ensure the Production client has access only to the services it needs.
See Authentication and Signing Requests for how to generate and rotate RSA‑2048 PEM keys and how to compute X-Custom-Signature.

Webhooks

  • Use distinct webhook endpoints per environment, e.g.:
    • Sandbox → https://staging.example.com/waftpay/callbacks
    • Production → https://merchant.example.com/waftpay/callbacks
  • Endpoints must be HTTPS and return a fast 2xx to acknowledge.
  • Verify the webhook signature using the same signing scheme used for requests.

Behavioural differences

  • Limits & throughput: Sandbox is throttled and may have lower throughput than Production.
  • Third‑party integrations: In Sandbox, payouts and collections are simulated and will not move real funds.
  • Errors: Error shapes and codes are identical across environments (see Errors).

Best practices

  • Treat Production credentials and keys as secrets; keep them out of client apps and repos.
  • Log the environment, request_id, and extended error code for every call.
  • Use idempotency on POSTs and ensure transaction.reference is unique per attempt.
  • Run end‑to‑end tests in Sandbox before promoting changes to Production.
  • Monitor webhooks separately per environment and alert on delivery failures.

See also