Core
Payments
Initiate mobile money payments, check status, and handle webhooks. Supports M-Pesa, Airtel Money, Mixx by Yas, and Halotel.
Payment Flow
Here's how a typical payment works end-to-end:
- Customer visits payment page (your-site.com/pay/your-slug)
- Customer enters phone number and amount
- Your backend calls POST /payments/checkout
- CamelPay creates a Snippe payment intent
- Customer receives USSD prompt on phone
- Customer enters PIN to authorize payment
- Snippe sends webhook to CamelPay
- CamelPay credits your wallet
- You receive webhook confirmation
Create a Payment Page
Before accepting payments, create a payment page:
bash
curl -X POST https://api.camelpay.in/payment-pages \
-H "Authorization: Bearer <your_jwt_token>" \
-H "Content-Type: application/json" \
-d '{
"type": "wallet_topup",
"title": "Campus Delivery Service",
"description": "Pay for your campus delivery",
"amount": 2000,
"allow_custom_amount": false,
"currency": "TZS"
}'Your payment URL will be: https://camelpay.in/pay/campus-delivery-service
Initiate a Payment
curl -X POST https://api.camelpay.in/payments/checkout \
-H "X-API-Key: cp_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"slug": "campus-delivery-service",
"phone_number": "+255712345678",
"customer_name": "John Doe",
"idempotency_key": "order_12345_67890"
}'Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Payment page slug |
phone_number | string | Yes | Customer's mobile money number (E.164 format) |
customer_name | string | Yes | Customer's name |
idempotency_key | string | Yes | Unique identifier for this transaction |
amount | integer | Conditional | Required if page allows custom amounts |
Check Payment Status
bash
curl -X GET https://api.camelpay.in/payments/snippe_ref_abc123/status \
-H "X-API-Key: cp_live_your_api_key_here"Status Values
| Status | Description |
|---|---|
pending | Awaiting customer action |
processing | Payment being processed |
completed | Payment successful, wallet credited |
failed | Payment failed or declined |
voided | Cancelled before completion |
expired | Payment expired (4 hour timeout) |
Polling Strategy
For real-time UI updates, poll the status endpoint:
async function pollPaymentStatus(reference, apiKey) {
const maxAttempts = 60; // 3 minutes with 3-second intervals
const interval = 3000;
for (let i = 0; i < maxAttempts; i++) {
const response = await fetch(
`https://api.camelpay.in/payments/${reference}/status`,
{ headers: { "X-API-Key": apiKey } }
);
const { data } = await response.json();
if (data.status === "completed") return { success: true, data };
if (data.status === "failed") return { success: false, error: "Payment failed" };
await new Promise(resolve => setTimeout(resolve, interval));
}
return { success: false, error: "Timeout" };
}Currency and Amounts
- Currency: TZS (Tanzanian Shilling) only
- Amount format: Integer (no decimals)
- Minimum amount: 500 TZS
- Example: 5000 TZS =
5000(not5000.00)
