Skip to main content
Use this endpoint to initiate a payment from your customer. You specify the payment method, amount, currency, and customer details. Kulmi Pay creates an invoice, triggers the appropriate payment network, and returns an invoice ID and JWT signature you use to track the transaction status. Method: POST
URL: https://app.kulmipay.com/api/v1/collect

Authentication

Authenticate with a Bearer token or by passing your public_key in the request body. Do not use both at the same time.
Authorization: Bearer <secret_key>

Request

Required fields

method
string
required
Payment method to use. One of: M-PESA, CARD-PAYMENT, APPLE-PAY, GOOGLE-PAY, PESALINK, BITCOIN, BANK-ACH.
currency
string
required
Transaction currency. One of: KES, USD, EUR, GBP. M-Pesa and PesaLink always settle in KES — if you pass a different currency, Kulmi Pay converts the amount using live exchange rates.
amount
string
required
Payment amount as a decimal string, for example "1500.00". For M-Pesa the minimum is KES 10 and the maximum is KES 150,000.
api_ref
string
required
Your unique reference for this payment, up to 140 characters. Store this value — you use it to reconcile transactions on your side.

Customer identity

phone_number
string
Customer phone number. Required for M-Pesa. Use international format, for example 254712345678.
email
string
Customer email address. Required for CARD-PAYMENT, BITCOIN, and BANK-ACH.
first_name
string
Customer first name. Required for CARD-PAYMENT and BANK-ACH.
last_name
string
Customer last name. Required for CARD-PAYMENT and BANK-ACH.

Authentication alternative

public_key
string
Your publishable API key. Use this instead of a Bearer token when calling from a client-side environment. Must match the environment (sandbox keys contain test, live keys contain live).

Fee configuration

mobile_tarrif
string
default:"BUSINESS-PAYS"
Who pays the processing fee for mobile money payments. Either BUSINESS-PAYS (fee deducted from your settlement) or CUSTOMER-PAYS (fee added to the customer-facing amount).
card_tarrif
string
default:"BUSINESS-PAYS"
Who pays the processing fee for card payments. Either BUSINESS-PAYS or CUSTOMER-PAYS.

Wallet routing

wallet_id
string
The alias ID of a specific wallet to receive the funds. If omitted, funds settle into your default settlement wallet for the transaction currency.

Card payment fields

The following fields are required when method is CARD-PAYMENT.
card_number
string
Full card number, digits only, up to 20 characters.
expiry
string
Card expiry date in MM/YY format, for example 08/27.
cvc
string
Card security code, 3–4 digits.
country
string
Two-letter ISO 3166-1 alpha-2 country code for the billing address, for example US. Required for card payments. Zipcode is also required when the country is US, CA, or GB.
zipcode
string
Postal or ZIP code for the billing address.
city
string
City for the billing address.
state
string
State or region for the billing address.
address
string
Street address for billing, up to 140 characters.

Response

invoice
object
Details of the invoice created for this payment.
signature
string
A JWT you use with the payment status endpoint to authenticate status checks without a server-side secret key. Store it alongside the invoice ID.

Code examples

curl --request POST \
  --url https://app.kulmipay.com/api/v1/collect \
  --header 'Authorization: Bearer YOUR_SECRET_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "method": "M-PESA",
    "currency": "KES",
    "amount": "1500.00",
    "api_ref": "order_20240416_001",
    "phone_number": "254712345678",
    "first_name": "Jane",
    "last_name": "Doe",
    "mobile_tarrif": "BUSINESS-PAYS"
  }'

Example response

{
  "invoice": {
    "id": "GQ7KZ2XPNM",
    "state": "PENDING",
    "value": "1500.00",
    "currency": "KES",
    "provider": "M-PESA",
    "api_ref": "order_20240416_001",
    "created_at": "2024-04-16T08:23:11.042Z"
  },
  "signature": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
For M-Pesa payments, the invoice state starts as PENDING. The customer receives an STK push prompt on their phone and must enter their PIN to complete the payment. Poll the payment status endpoint or use webhooks to detect when the state changes to COMPLETE or FAILED.