Cowdidocs
API ReferenceTransactions

Transfer between the caller's accounts

POST
/v1/transactions/transfers

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.

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 transfer money between two of the caller's own accounts. The current version supports one pair: from a current account to a lending account.

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/transfers" \  -H "Idempotency-Key: string" \  -H "Content-Type: application/json" \  -d '{    "from_account_id": "550e8400-e29b-41d4-a716-446655440000",    "to_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",    "amount": {      "value": 50000,      "currency": "KES"    }  }'
{  "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"}