Authentication required.
Generate your own API key — no signup, no env vars:
Or call POST https://nobody-needs-this.vercel.app/api/keys with an empty JSON body.
Send your key on every request (except public routes):
Authorization: Bearer YOUR_API_KEY
X-API-Key: YOUR_API_KEY
Revoke: DELETE /api/keys with your key. Admin routes need ADMIN_API_KEY in production.
Base URL: https://nobody-needs-this.vercel.app
All requests use Content-Type: application/json unless noted.
Endpoints
GET
Health check
/api/health
Public
Returns service status. No authentication required.
Example response
{ "status": "healthy", "service": "payment-simulator", "environment": "production", "auth_required": true, "registration_enabled": true, "api_key_store": "redis" }
POST
Create API key
/api/keys
Public
Generate a personal API key (shown once). No auth required when ENABLE_API_KEY_REGISTRATION is true. Rate-limited per IP.
curl -X POST "https://nobody-needs-this.vercel.app/api/keys" \
-H "Content-Type: application/json" \
-d '{}'
Example response
{ "success": true, "api_key": "ps_live_…", "message": "Save this key now…" }
DELETE
Revoke API key
/api/keys
API key required
Revokes the API key sent on this request. Bootstrap/env keys cannot be revoked via this endpoint.
Example response
{ "success": true, "message": "API key revoked" }
POST
M-Pesa STK Push
/api/payments/mpesa/stk-push
API key required
Initiate a fake M-Pesa STK push. With auto_complete (default true), a callback is simulated after ~2 seconds.
| Field | | Notes |
phone_number |
yes |
254XXXXXXXXX |
amount |
yes |
Number |
account_reference |
no |
Default: TEST |
description |
no |
Default: Payment |
callback_url |
no |
Webhook URL when payment completes |
auto_complete |
no |
true = simulate callback after ~2s (default true) |
force_success |
no |
true / false / omit for random (~95% success) |
curl -X POST "https://nobody-needs-this.vercel.app/api/payments/mpesa/stk-push" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phone_number":"254712345678","amount":1000,"account_reference":"ORDER-123","description":"Payment","callback_url":"https://your-app.com/webhooks/mpesa","auto_complete":true,"force_success":true}'
POST
M-Pesa callback (manual)
/api/payments/mpesa/callback
API key required
Manually trigger the M-Pesa STK callback for a transaction. Use when auto_complete is false.
| Field | | Notes |
transaction_id |
yes |
From stk-push response |
force_success |
no |
true = success (0), false = cancelled (1032) |
curl -X POST "https://nobody-needs-this.vercel.app/api/payments/mpesa/callback" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"transaction_id":"MPXABC123","force_success":true}'
POST
Bank transfer
/api/payments/bank-transfer
API key required
Initiate a fake bank transfer. Auto-completes after ~3 seconds when auto_complete is true.
| Field | | Notes |
account_number |
yes |
Beneficiary account |
bank_code |
yes |
Bank identifier |
amount |
yes |
Number |
reference |
no |
Default: TEST |
narration |
no |
Default: Payment |
callback_url |
no |
Webhook URL on completion |
auto_complete |
no |
Default true |
force_success |
no |
true / false / random |
curl -X POST "https://nobody-needs-this.vercel.app/api/payments/bank-transfer" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"account_number":"1234567890","bank_code":"01","amount":5000,"reference":"INV-123","narration":"Supplier payment","callback_url":"https://your-app.com/webhooks/bank","auto_complete":true,"force_success":true}'
POST
Bank transfer complete (manual)
/api/payments/bank-transfer/complete
API key required
Manually complete a bank transfer when auto_complete is false.
| Field | | Notes |
transaction_id |
yes |
From bank-transfer response |
force_success |
no |
true = completed, false = failed |
curl -X POST "https://nobody-needs-this.vercel.app/api/payments/bank-transfer/complete" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"transaction_id":"BNKABC123","force_success":true}'
GET
Transaction status
/api/payments/:transaction_id
API key required
Get the current state of a single transaction.
| Field | | Notes |
transaction_id |
yes |
Path parameter, e.g. MPX… or BNK… |
GET
List transactions
/api/payments
API key required
List in-memory transactions. Optional query filters.
| Field | | Notes |
status |
query |
pending | processing | completed | failed | cancelled |
method |
query |
mpesa | bank_transfer |
POST
Reset all transactions
/api/payments/reset
Admin key required in production
Clears all stored transactions. In production requires ADMIN_API_KEY.
curl -X POST "https://nobody-needs-this.vercel.app/api/payments/reset" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'
Webhooks
Include callback_url when starting a payment. When the flow completes, the simulator POSTs JSON to that URL (same shape as real providers).
For local testing, run ruby webhook_receiver.rb on port 4567 and use:
http://localhost:4567/webhooks/mpesa (local receiver)
…/webhooks/bank
On serverless hosts (e.g. Vercel), prefer auto_complete: false and call the manual callback endpoints, or use a public inbox like webhook.site.
M-Pesa result codes
| Code | Meaning |
0 | Success |
1032 | User cancelled |
1037 | Timeout (no PIN) |
2001 | Wrong PIN |
1 | Insufficient balance |