---
title: "Initiate STK Push"
method: POST
path: "/payments/stk"
tags: ["STK Push"]
---

# Initiate STK Push

`POST /payments/stk`

Sends an M-Pesa STK Push prompt to the customer's phone. The customer enters
their M-Pesa PIN to authorise payment.

Payment results are delivered **asynchronously** to the `callbackUrl` you supply.
Poll `GET /transactions/{id}` if you need to check status programmatically.

**Fees:** A transaction fee is deducted from your service wallet balance at the
time the request is accepted. If your balance is insufficient the request returns `402`.

## Request body

- StkInitiateRequest
  - `amount` number, required — Amount to charge in KES.
  - `phone` string, required — Customer phone number. Accepted formats: `0712345678`, `254712345678`, `+254712345678`. Normalised to `254XXXXXXXXX` internally.
  - `accountReference` string, required — Your reference — invoice number, order ID, etc.
  - `transactionDesc` string, required — Short description shown on the customer's PIN prompt.
  - `callbackUrl` string, uri, required — HTTPS URL where PalPluss will POST the transaction result after the customer confirms or cancels payment.
  - `channelId` string, uuid, nullable — Optional. Route the STK Push through a specific payment channel (shortcode). If omitted, the default channel is used.
  - `credential_id` string, uuid, nullable — Optional. Use a specific MERCHANT_BYOC credential profile for this request. When provided, Daraja OAuth and STK initiation use that profile's credentials (`consumerKey`, `consumerSecret`, `passkey`, `shortcode`). **Transaction type (`commandId`) resolution when `credential_id` is set:** - Channel present → channel type drives it (`PAYBILL` = CustomerPayBillOnline, `TILL` = CustomerBuyGoodsOnline) - No channel → profile's `transactionType` is used when set; falls back to platform default **`PartyB` resolution when no channel is configured:** the credential profile's shortcode is used instead of the platform default shortcode.

## Response `200`

STK Push accepted. Transaction is in `PENDING` state.

- object
  - `success` boolean, required
  - `data` object, required — Response payload. Shape varies by endpoint.
    - `transactionId` string, uuid
    - `tenantId` string, uuid
    - `channelId` string, uuid, nullable
    - `type` string
    - `status` string
    - `amount` number
    - `currency` string
    - `phone` string
    - `accountReference` string
    - `transactionDesc` string
    - `providerRequestId` string, nullable
    - `providerCheckoutId` string, nullable
    - `transactionFee` number — Service wallet fee charged for this request in KES. `0` when no pricing rule is configured or the transaction did not succeed.
    - `resultCode` string, nullable
    - `resultDescription` string, nullable
    - `createdAt` string, date-time
    - `updatedAt` string, date-time
  - `requestId` string, uuid, required — Unique identifier for this API request. Include in support tickets.

## Other responses

- `400` — Bad request — validation error or channel not configured.
- `401` — Missing, invalid, or revoked API key.
- `402` — Service wallet balance is too low to cover the transaction fee.
- `404` — The requested resource does not exist.
- `429` — Rate limit exceeded — 60 requests per minute per API key.

---

[API](https://skmtc.dev/palpluss/apis/palpluss-api.md) · [All operations](https://skmtc.dev/palpluss/apis/palpluss-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/palpluss/palpluss-api/revisions/33fd40a3b314/schema)
