Cowdidocs
API ReferenceTransactions

Create a payee transaction

POST
/v1/transactions/payees

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.

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 a transaction to one of the caller's saved payee accounts.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/transactions/payees" \  -H "Idempotency-Key: string" \  -H "Content-Type: application/json" \  -d '{    "account_id": "550e8400-e29b-41d4-a716-446655440000",    "amount": {      "value": 50000,      "currency": "KES"    },    "payee_account_id": "7b9d4f2e-1c3a-4d5b-8e6f-9a0b1c2d3e4f"  }'
{  "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": "BAD_REQUEST",  "description": "Invalid input"}
{  "code": "RATE_LIMIT_EXCEEDED",  "description": "Too Many Requests"}
{  "code": "INTERNAL_ERROR",  "description": "Internal Server Error"}

Create an M-Pesa STK Push collection POST

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.

Preview a transaction POST

Price a transaction before creating it. Set `type` to `SEND_MONEY`, `BUY_GOODS`, `PAY_BILL`, `POCHI`, or `PAYEE` to match the intended create operation. Requires an authenticated, active user. Every loan or credit account returns `loan_options`. The top-level `loan` field is deprecated in its favor. For `FLEX_CREDIT`, send `tenure` to price that option alone, or omit it to price every available tenure. `fee`, `total`, and `loan` are then absent, so read `loan_options` instead. Omit `tenure` for other account types. Returns 404 when `account_id`, or a `PAYEE` request's `payee_account_id`, does not belong to the caller. A `POCHI` preview, or a `PAYEE` preview of a `POCHI` payee account, refuses `POCHI_NOT_SUPPORTED_FOR_ACCOUNT`, `POCHI_NOT_AVAILABLE`, and `POCHI_AMOUNT_OUT_OF_RANGE`.