Skip to content

Pesapal API 3.0 Request Builder

Copy-paste code for every step of a Pesapal API 3.0 integration, in four languages, with the order id, IPN id and URLs checked as you type. Everything runs in your browser; your keys never leave this page.

Request

Step

Code

    Expected response
    Then
    Your .env file

    PHP output reads config('services.pesapal.consumer_key'), consumer_secret and access_token. Map them to these variables in config/services.php.

    How a Pesapal API 3.0 payment works

    1. Get a token with your consumer key and secret. It lasts at most 5 minutes.
    2. Register your IPN URL once per environment, and keep the ipn_id.
    3. Submit the order with your own id, the amount, currency, callback_url, notification_id (the ipn_id) and the customer's email or phone. Save the order first.
    4. Send the customer to the redirect_url in the response. They choose how to pay on Pesapal's page.
    5. Pesapal redirects them to your callback_url and calls your IPN URL, both with OrderTrackingId, OrderMerchantReference and OrderNotificationType (CALLBACKURL or IPNCHANGE). Neither includes the status.
    6. Check the status with GetTransactionStatus, and settle the order from that answer.

    Base URLs

    Sandbox: https://cybqa.pesapal.com/pesapalv3. Live: https://pay.pesapal.com/v3. The two have separate keys and separate IPN registrations. Pesapal publishes demo keys for the sandbox, linked from its authentication docs.

    Transaction statuses

    status_codepayment_status_descriptionWhat to do
    1COMPLETEDCheck merchant_reference, amount and currency, then fulfil once.
    2FAILEDMark unpaid; let the customer try again with a new order id.
    3REVERSEDIf you fulfilled it, treat the payment as taken back.
    0INVALIDNot paid. Keep checking, and expire the order if it never completes.

    Every status, and what Pesapal's error object looks like, is in the Pesapal error reference.

    What the docs don't say

    • The phone number format for billing_address.phone_number. Send the email address too when you can.
    • What your server must answer to an IPN. The Node.js guide answers 200 with the values it received, and runs a reconcile job so a missed IPN never leaves an order stuck.
    • A list of error codes. Errors come as an object with type, code and message: log all three.

    Frequently asked questions

    What is notification_id in Pesapal SubmitOrderRequest?

    It is the ipn_id returned when you register your IPN URL with POST /api/URLSetup/RegisterIPN. Register once per environment (sandbox and live are separate) and send the same ipn_id with every order.

    How long is a Pesapal API 3.0 token valid?

    At most 5 minutes, according to Pesapal. The response includes expiryDate in UTC. Cache the token and renew it shortly before it expires.

    Why doesn't the Pesapal IPN include the payment status?

    Pesapal says the callback and IPN calls leave the status out for security reasons. They give you the OrderTrackingId; call GetTransactionStatus with it and use that answer.

    What characters can the order id contain?

    Letters, numbers, hyphens, underscores, full stops and colons, up to 50 characters. Spaces and symbols such as @ # $ % & / \ ? = are not allowed, and the id must be unique for every order request.

    Can I cancel or refund a Pesapal order from the API?

    Yes. CancelOrder works only for failed or pending payments, once. RefundRequest works only for COMPLETED payments, once, in the same currency; mobile money is refunded in full only, cards in full or in part, and you must approve the refund.

    Related

    Endpoints and fields checked November 2026 against Pesapal's API 3.0 documentation at developer.pesapal.com.

    Need this built for you?

    I integrate MTN MoMo, M-Pesa and Airtel Money into Laravel / PHP, Python / Django, Node.js / Next.js apps: payments, callbacks, payouts and go-live, with tests.