Cowdidocs
API ReferenceTransactions

Create an M-Pesa STK Push collection

POST
/v1/transactions/mpesa/stk-push

Create an M-Pesa STK Push collection from a phone number into one of the caller's accounts. Requires an authenticated, active user. A current-account deposit requires the account owner's own phone number. A credit-account repayment accepts any payer's phone number. For FLEX_CREDIT, disbursement_id is optional, and when set it must name the oldest open disbursement. Repayment first pays the due installments of every purchase. It then pays the installments of the next due date on every purchase. The rest pays the oldest purchase first. A repeated request with the same Idempotency-Key header replays the first response instead of creating a second collection, and reusing the key with a different request body returns 409. Returns 404 when account_id does not belong to the caller.

AuthorizationBearer <token>

Create a client with POST /v1/oauth/clients, then exchange its credentials for an access token. AUTHORIZATION_CODE clients act on behalf of a signed-in user and always use PKCE; CLIENT_CREDENTIALS clients act as themselves. A client may only be granted scopes its creator already holds — read the grantable list from GET /v1/oauth/clients/scopes.

In: header

Header Parameters

Idempotency-Key*string

Unique key that de-duplicates retries of this request: the first call executes and its response is stored, identical retries replay it, and reusing a key with a different request body is rejected with 409 Conflict.

Lengthlength <= 255

Request Body

application/json

Request to create an M-Pesa STK Push collection from a phone number.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/transactions/mpesa/stk-push" \  -H "Idempotency-Key: string" \  -H "Content-Type: application/json" \  -d '{    "account_id": "550e8400-e29b-41d4-a716-446655440000",    "amount": {      "value": 150000,      "currency": "KES"    },    "mobile_number": "+254712345678"  }'
{  "id": "01a11715-7b0d-7e3f-9c2a-4d5e6f708192",  "resource_id": "trx_01m4bhayrdfrzsrajdbsqq10cj",  "mpesa_transaction_id": "ABCDE12345",  "amount": {    "value": 100000,    "currency": "KES"  },  "fee_amount": {    "value": 5000,    "currency": "KES"  },  "status": "COMPLETED",  "failure_reason": null,  "transacted_at": "2026-01-20T10:30:00Z",  "confirmed_at": "2026-01-20T10:30:05Z",  "posted_at": "2026-01-20T10:30:10Z",  "failed_at": null,  "details": {    "type": "BUY_GOODS",    "till_number": "12345"  }}
{  "code": "BAD_REQUEST",  "description": "Bad Request"}
{  "code": "UNAUTHORISED",  "description": "Unauthorised"}
{  "code": "FORBIDDEN",  "description": "Forbidden"}
{  "id": "01a11715-7b0d-7e3f-9c2a-4d5e6f708192",  "resource_id": "trx_01m4bhayrdfrzsrajdbsqq10cj",  "mpesa_transaction_id": "ABCDE12345",  "amount": {    "value": 100000,    "currency": "KES"  },  "fee_amount": {    "value": 5000,    "currency": "KES"  },  "status": "COMPLETED",  "failure_reason": null,  "transacted_at": "2026-01-20T10:30:00Z",  "confirmed_at": "2026-01-20T10:30:05Z",  "posted_at": "2026-01-20T10:30:10Z",  "failed_at": null,  "details": {    "type": "BUY_GOODS",    "till_number": "12345"  }}
{  "id": "01a11715-7b0d-7e3f-9c2a-4d5e6f708192",  "resource_id": "trx_01m4bhayrdfrzsrajdbsqq10cj",  "mpesa_transaction_id": "ABCDE12345",  "amount": {    "value": 100000,    "currency": "KES"  },  "fee_amount": {    "value": 5000,    "currency": "KES"  },  "status": "COMPLETED",  "failure_reason": null,  "transacted_at": "2026-01-20T10:30:00Z",  "confirmed_at": "2026-01-20T10:30:05Z",  "posted_at": "2026-01-20T10:30:10Z",  "failed_at": null,  "details": {    "type": "BUY_GOODS",    "till_number": "12345"  }}
{  "code": "RATE_LIMIT_EXCEEDED",  "description": "Too Many Requests"}
{  "code": "INTERNAL_ERROR",  "description": "Internal Server Error"}

Create an M-Pesa send-money payment POST

Create an M-Pesa send-money payment from one of the caller's accounts. Requires an authenticated, active user. Returns the transaction. It starts `PENDING` and moves to `CONFIRMED` or `FAILED` as M-Pesa, and any required OTP, confirm it. For a `FLEX_CREDIT` account, get `GET /v1/accounts/flex/{account_id}/tenure/options` and send the chosen option's `tenure`. Omit `tenure` for other account types. A repeated request with the same `Idempotency-Key` header replays the first response instead of creating a second payment, and reusing the key with a different request body returns 409. Returns 404 when `account_id` does not belong to the caller, and 422 when the mobile number matches a payee the caller has blocked.

Create a payee transaction POST

Create a transaction to one of the caller's saved payee accounts. The server resolves the destination from `payee_account_id` and routes the payment the same way as the matching M-Pesa surface. Requires an authenticated, active user. For a `FLEX_CREDIT` account, get `GET /v1/accounts/flex/{account_id}/tenure/options` and send the chosen option's `tenure`. Omit `tenure` for other account types. A repeated request with the same `Idempotency-Key` header replays the first response instead of creating a second payment, and reusing the key with a different request body returns 409. Returns 404 when `account_id` or `payee_account_id` does not belong to the caller, and 422 when the payee is blocked. Returns 409 `LOAN_REPAYMENT_PAYBILL_NOT_SUPPORTED` when the payee account is a Cowdi loan repayment destination. A payment to a `POCHI` payee account is a Pochi la Biashara payment. It follows the rules of `POST /v1/transactions/mpesa/pochi`.