PRINTPAY
Profile
Printpay C2B API Documentation
Developer documentation

C2B Payments API

Integrate M-Pesa STK Push payments into your application. Initiate payment prompts, verify transaction status, and receive callback notifications using the Printpay API.

M-Pesa STK Push REST API JSON & Form Requests

Endpoint overview

All endpoints use your current host with the fixed /api/ base path.

Operation Method Endpoint Purpose
STK Push POST Initiate a customer payment prompt.
Check status GET Check a transaction's status.
Callback POST Receive payment notifications.

Authentication

Keep your merchant API key private and make payment requests from your server.

Field Type Location Purpose
x_api_key String STK Push request body Authenticates your merchant account.
Do not place production API keys in frontend JavaScript, public repositories, or client apps. Load the key from a secure server-side environment variable.

Initiate an STK Push

Ask the customer to authorize a payment on their phone.

A successful initiation response only means the request was accepted. Confirm the final payment result through the status endpoint or a verified callback.

POST
Parameter Type Required Description
x_api_key String Yes Your merchant API key.
phone_number String Yes Customer phone number, e.g. 0712345678 or 254712345678.
amount Integer Yes Payment amount in KES.
<?php
$url = "https://printpay.co.ke.helapull.com/api/stk_push";

$payload = [
    'x_api_key'    => getenv('PRINTPAY_API_KEY'),
    'phone_number' => '0712345678',
    'amount'       => 10,
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => http_build_query($payload),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_TIMEOUT        => 30,
]);

$response = curl_exec($ch);

if ($response === false) {
    throw new RuntimeException(curl_error($ch));
}

curl_close($ch);
echo $response;
?>
Example initiation response: {"status":"success","checkout_id":"ws_CO_..."}. Use the actual response fields returned by your API.

Check transaction status

Use the checkout ID returned by the STK Push request.

GET

Query parameter: check_status. Respect your API's rate limits when polling.

<?php
$checkoutId = 'ws_CO_070720261234567890';

$url = "https://printpay.co.ke.helapull.com/api/stk_push?check_status="    . rawurlencode($checkoutId);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_TIMEOUT        => 30,
]);

$response = curl_exec($ch);

if ($response === false) {
    throw new RuntimeException(curl_error($ch));
}

curl_close($ch);
echo $response;
?>
Successful payment
{
  "id": "241",
  "status": "SUCCESS",
  "phone_number": "254712345678",
  "amount": "10.00",
  "mpesa_receipt_number": "TGR7XYZ890"
}
Pending payment
{
  "id": "241",
  "status": "PENDING",
  "phone_number": "254712345678",
  "amount": "10.00",
  "mpesa_receipt_number": null
}

Callback notifications

Receive transaction updates at your configured callback URL.

Configure your callback URL in the relevant merchant settings. Confirm the callback method, payload, and registration requirements against your deployed API.

POST
{
  "checkout_id": "ws_CO_070720261234567890",
  "status": "SUCCESS",
  "mpesa_receipt": "TGR7XYZ890",
  "amount": 10.00,
  "phone": "254712345678",
  "result_code": 0
}
Treat this as an illustrative payload only. Verify callback authenticity, validate amount and receipt, and update transactions idempotently before fulfilling an order.

Common result codes

Example meanings often seen in M-Pesa STK integrations.

Code Status Typical meaning
0 SUCCESS Transaction reported as successful. Verify receipt and amount before fulfilling an order.
1032 FAILED Commonly associated with a customer-cancelled STK request.
1037 FAILED / TIMEOUT Commonly associated with a request timeout or unreachable handset.
2001 FAILED Commonly associated with an invalid or rejected customer PIN.
Confirm result-code meanings against the Safaricom and Printpay API versions you use. The deployed gateway's documentation is authoritative.