Preview a transaction
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.
Authorization
oauth2 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
Request Body
application/json
Request to preview an M-Pesa buy-goods payment.
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/preview" \ -H "Content-Type: application/json" \ -d '{ "type": "BUY_GOODS", "account_id": "550e8400-e29b-41d4-a716-446655440000", "amount": { "value": 50000, "currency": "KES" }, "till_number": "123456", "recipient_name": "ABC Store" }'{ "type": "SEND_MONEY", "amount": 30000, "fee": 1100, "total": 31100, "channel": "MPESA", "currency": "KES", "can_proceed": true, "validation": { "account_valid": true, "account_name": "John D****** O******", "name_match": "PARTIAL_MATCH", "validation_message": "The name 'John Doe' partially matches the account holder 'John D****** O******'. Please confirm this is the correct recipient.", "requires_confirmation": true }}{ "code": "BAD_REQUEST", "description": "Bad Request"}{ "code": "UNAUTHORISED", "description": "Unauthorised"}{ "code": "FORBIDDEN", "description": "Forbidden"}{ "type": "SEND_MONEY", "amount": 30000, "fee": 1100, "total": 31100, "channel": "MPESA", "currency": "KES", "can_proceed": true, "validation": { "account_valid": true, "account_name": "John D****** O******", "name_match": "PARTIAL_MATCH", "validation_message": "The name 'John Doe' partially matches the account holder 'John D****** O******'. Please confirm this is the correct recipient.", "requires_confirmation": true }}{ "code": "BAD_REQUEST", "description": "Invalid input"}{ "code": "RATE_LIMIT_EXCEEDED", "description": "Too Many Requests"}{ "code": "INTERNAL_ERROR", "description": "Internal Server Error"}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`.
Transfer between the caller's accounts POST
Transfer money between two of the caller's own accounts. The current version supports one pair: a current account pays a lending account. Requires an authenticated, active user. The custodian sends the caller an OTP, and the transaction waits in `PENDING_OTP_CONFIRMATION` until the caller confirms it with `POST /v1/transactions/{id}/confirm`. Both accounts record the transfer, with the counterparty account, in their transaction details. A repeated request with the same `Idempotency-Key` header replays the first response instead of creating a second transfer, and reusing the key with a different request body returns 409. Returns 404 when `from_account_id` or `to_account_id` does not belong to the caller, and 400 when the accounts are not a current-to-lending pair, use different currencies, or the amount exceeds the destination's outstanding balance.