Language

Receive funds from M-PESA users

Step 1: Obtain an application access token

Your application will need to exchange its client_id, client_secret, and grant_type=client_credentials for an application access token. With this token, you can then make API requests to the Kopo Kopo API.

Step 2: Make incoming payment request

Make a payment request to the Kopo Kopo API. The request payload will need to include the first name, last name, phone number, amount to debit and optionally email of the user / subscriber that is to be debited.

The till number used for the STK request should be from the Online Payments Account, and is prefixed with a K.

POST https://sandbox.kopokopo.com/api/v1/incoming_payments
Content-Type: application/json
Accept: application/json
Authorization: Bearer 0Sn0W6kzNicvoWhDbQcVSKLRUpGjIdlPSEYyrHqrDDoRnQwE7Q
{
  "payment_channel": "M-PESA STK Push",
  "till_number": "K000000",
  "subscriber": {
    "first_name": "Joe",
    "last_name": "Buyer",
    "phone_number": "+254999999999"
    "email": "jbuyer@mail.net"
  },
  "amount": {
    "currency": "KES",
    "value": 20000
  },
  "metadata":{
    "customer_id": "123456789",
    "reference": "123456",
    "notes": "Payment for invoice 12345"
  },
  "_links" : {
    "callback_url": "https://call_back_to_your_app.your_application.com"  
  }
}

HTTP/1.1 201 Created
Location: https://sandbox.kopokopo.com/api/v1/incoming_payments/247b1bd8-f5a0-4b71-a898-f62f67b8ae1c
# Input to send
example_input = {
        payment_channel: 'M-PESA',
        till_number: 'K000000',
        first_name: 'first_name',
        last_name: 'last_name',
        phone_number: '+254999999999',
        email: 'email@emailc.om',
        currency: 'currency',
        value: 2000,
        metadata: {
            customer_id: 123_456_789,
            reference: 123_456,
            notes: 'Payment for invoice 12345'
        },
        callback_url: 'https://webhook.site/437a5819-1a9d-4e96-b403-a6f898e5bed3'
    }

# Using K2Connect - https://github.com/kopokopo/k2-connect-ruby (Recommended)
k2_stk = K2Stk.new('your_access_token')
k2_stk.receive_mpesa_payments(example_input)
k2_stk.location_url # => "https://sandbox.kopokopo.com/api/v1/incoming_payments/247b1bd8-f5a0-4b71-a898-f62f67b8ae1c"

const StkService = K2.StkService

var stkOptions = {
  paymentChannel: "M-PESA STK Push",
  tillNumber: "K000000",
  firstName: 'Jane',
  lastName: 'Doe',
  phoneNumber: '+254999999999',
  email: 'example@example.com',
  currency: 'KES',
  // A maximum of 5 key value pairs
  metadata: {
    customerId: '123456789',
    reference: '123456',
    notes: 'Payment for invoice 123456'
  },
    // This is where once the request is completed kopokopo will post the response
    callbackUrl: 'https://callback_to_your_app.your_application.com/endpoint',
    accessToken: 'myRand0mAcc3ssT0k3n'
}

StkService
  .initiateIncomingPayment(stkOptions)
  .then( response => {     
    console.log(response)
    // => 'https://sandbox.kopokopo.com/api/v1/incoming_payments/247b1bd8-f5a0-4b71-a898-f62f67b8ae1c'
  })
  .catch( error => {
    console.log(error)
  })
# Using Kopo Kopo Connect - https://github.com/kopokopo/k2-connect-python (Recommended)
k2connect.initialize(CLIENT_ID, CLIENT_SECRET, BASE_URL)
stk_service = k2connect.ReceivePayments

request_body =
{
  "access_token": ACCESS_TOKEN,
  "callback_url": "https://webhook.site/52fd1913-778e-4ee1-bdc4-74517abb758d",
  "first_name": "python_first_name",
  "last_name": "python_last_name",
  "email": "test@gmail.com",
  "payment_channel": "MPESA",
  "phone_number": "+254911222536",
  "till_number": "K000000",
  "amount": "10"
}

stk_push_location = stk_service.create_payment_request(request_body)
stk_push_location # => 'https://sandbox.kopokopo.com/api/v1/incoming_payments/247b1bd8-f5a0-4b71-a898-f62f67b8ae1c'

<?
$stk = $K2->StkService();

$response = $stk->initiateIncomingPayment([
  'paymentChannel' => 'M-PESA STK Push',
  'tillNumber' => 'K000000',
  'firstName' => 'Jane',
  'lastName' => 'Doe',
  'phoneNumber' => '+254999999999',
  'amount' => 3455,
  'currency' => 'KES',
  'email' => 'example@example.com',
  'callbackUrl' => 'https://callback_to_your_app.your_application.com/endpoint',
  'accessToken' => 'myRand0mAcc3ssT0k3n',
]);

if($response['status'] == 'success')
{
    echo "The resource location is:" . json_encode($response['location']);
    // => 'https://sandbox.kopokopo.com/api/v1/incoming_payments/247b1bd8-f5a0-4b71-a898-f62f67b8ae1c'
}

When the Payment Request has been successfully received, you will receive the Payment Request URL in the location header. Kopo Kopo will then process the Incoming Payment Request and the result will be sent asynchronously to they callback URL specified.

Step 3: Receive and process the Incoming Payment Request Result

Once you have sent a Payment Request, the results and status of the request will be posted back to the Callback URL that you specified in Step 2. Your end point needs to be a secure end point protected with TLS (HTTPS).

Example of Incoming Payment Request Result payload when transaction is successful

{
  "data": {
    "id": "49b2bf39-0bff-4f37-8b19-43ca21ab3bf2",
    "type": "incoming_payment",
    "attributes": {
      "initiation_time": "2020-10-21T09:30:34.331+03:00",
      "status": "Success",
      "event": {
        "type": "Incoming Payment Request",
        "resource": {
          "id": "f39-0bff-44ef4-0629-481f-83cd-d101f",
          "reference": "OJL7OW3J59",
          "origination_time": "2020-10-21T09:30:40+03:00",
          "sender_phone_number": "+254999999999",
          "amount": "100.0",
          "currency": "KES",
          "till_number": "K000000",
          "system": "Lipa Na M-PESA",
          "status": "Received",
          "sender_first_name": "Joe",
          "sender_middle_name": null,
          "sender_last_name": "Buyer"
        },
        "errors": null
      },
      "metadata": {
        "customer_id": "123456789",
        "reference": "123456",
        "notes": "Payment for invoice 12345"
      },
      "_links": {
        "callback_url": "https://webhook.site/675d4ef4-0629-481f-83cd-d101f55e4bc8",
        "self": "https://sandbox.kopokopo.com/api/v1/incoming_payments/49b2bf39-0bff-4f37-8b19-43ca21ab3bf2"
      }
    }
  }
}

Example of Incoming Payment Request result payload when the transaction fails

{
  "data": {
    "id": "b01ac495-0969-4a7d-b35a-57ccbf541f1d",
    "type": "incoming_payment",
    "attributes": {
      "initiation_time": "2020-10-19T09:23:41.362+03:00",
      "status": "Failed",
      "event": {
        "type": "Incoming Payment Request",
        "resource": null,
        "errors": "The initiator information is invalid."
      },
      "metadata": {
        "customer_id": "123456789",
        "reference": "123456",
        "notes": "Payment for invoice 12345"
      },
      "_links": {
        "callback_url": "https://webhook.site/675d4ef4-0629-481f-83cd-d101f55e4bc8",
        "self": "https://sandbox.kopokopo.com/api/v1/incoming_payments/b01ac495-0969-4a7d-b35a-57ccbf541f1d"
      }
    }
  }
}

If an error occurs and the payment request fails for one reason or another, there will be no corresponding transaction resource and the errors encountered will be contained in an array in the event item of the JSON payload. Please note if you have also subscribed for the buygoods_transaction_received event webhook, you will also receive a notification of this transaction to the url specified in the webhook subscription.