Overview
The Codian API suite enables developers to integrate payments, chatbots, emails, SMS, and airtime services into their applications. All APIs use JSON payloads and are compatible with any programming language that supports HTTP requests, such as Python, JavaScript, PHP, Ruby, or Go.
API Services
- Payments API: Facilitates M-Pesa payments through Custom Integration (full control) or Managed Integration (low-code).
- Chatbots API: Enables the creation of conversational bots for user engagement and task automation.
- Emails API: Supports sending transactional or bulk emails with customizable templates.
- SMS API: Allows sending SMS notifications or campaigns.
- Airtime API: Facilitates mobile airtime top-ups across supported networks.
Getting Started
Create a Codian Account
To begin, create a developer account at codian.co.ke/accounts/signup.php. After signing up, log in to your dashboard to create an app and obtain your client_id and client_secret.
Prerequisites
- A Codian developer account with API credentials (Client ID & Secret).
- An HTTPS-enabled website for production (localhost is acceptable for testing).
- IMPORTANT: A webhook endpoint configured in the Codian dashboard to receive real-time transaction updates. The endpoint must return HTTP 200 to confirm receipt.
- Basic knowledge of HTTP requests (POST, JSON, etc.) in your preferred programming language.
Step 1: Obtain Credentials
Log in to your Codian dashboard, create an app, and retrieve your client_id and client_secret.
Client ID: codian_prd_XXXXXXXXXX
Client Secret: codian_sk_prd_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Step 2: Secure Credentials
Store your credentials securely:
- Hardcoded: Suitable for quick development testing but not recommended for production.
- Environment Variables: Recommended for secure storage in production environments.
Payments API
Two Integration Methods
Codian offers two distinct methods for integrating M-Pesa payments. Choose the one that best fits your needs:
Build your own payment forms and handle the complete user experience. Ideal for developers who want full control.
Features:
- Direct STK Push initiation
- Custom UI/UX for payment forms
- Receive callbacks to your webhook
- Full control over transaction flow
Let Codian handle the payment flow including forms, STK Push, and redirects. Perfect for quick integrations.
Features:
- Codian-hosted payment pages
- Receive callbacks to your webhook
- Redirect-based flow
- Minimal code required
Payments API: Custom Integration
Overview
The Custom Integration gives you full control over the payment experience. You build your own payment forms and initiate M-Pesa STK Push directly. Transaction updates are sent to your webhook endpoint configured in the Codian dashboard.
Endpoint URLs
- Sandbox:
https://sandbox.codian.co.ke/v1/payments/c2b/initiate/ - Production:
https://api.codian.co.ke/v1/payments/c2b/initiate/
Payload Structure
Send a JSON payload to the appropriate endpoint. This is the correct payload structure for Custom Integration.
| Field | Type | Description | Example |
|---|---|---|---|
| client_id | string | Your Codian Client ID | codian_prd_j2T2i15dg5 |
| client_secret | string | Your Codian Client Secret | codian_sk_prd_FSCzai6tHjad99FBGP34j1fs61sw0N |
| amount | number | Amount in KES (min 1) | 50.00 |
| phone | string | M-Pesa registered phone number (format: 2547XXXXXXXX or 07XXXXXXXX) | 254794335725 or 0712345678 |
{
"client_id": "codian_prd_j2T2i15dg5",
"client_secret": "codian_sk_prd_FSCzai6tHjad99FBGP34j1fs61sw0N",
"amount": 50.00,
"phone": "254794335725"
}
Integration Example (PHP)
This is a complete working example showing how to initiate an STK Push using the Custom Integration:
<?php
// Prepare Codian API payload
$client_id = 'codian_prd_j2T2i15dg5';
$client_secret = 'codian_sk_prd_FSCzai6tHjad99FBGP34j1fs61sw0N';
$amount = 50.00;
$phone = '254794335725'; // Format: 2547XXXXXXXX
$payload = [
"client_id" => $client_id,
"client_secret" => $client_secret,
"amount" => $amount,
"phone" => $phone
];
// Initiate payment via Codian API
$ch = curl_init('https://api.codian.co.ke/v1/payments/c2b/initiate/');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_error = curl_error($ch);
curl_close($ch);
if ($curl_error) {
die('CURL Error: ' . $curl_error);
}
if (!$response) {
die('Empty response from payment gateway');
}
$data = json_decode($response, true);
if ($http_code === 200 && isset($data['success']) && $data['success']) {
// Extract checkout request ID for tracking
$checkout_id = '';
if (isset($data['CheckoutRequestID'])) {
$checkout_id = $data['CheckoutRequestID'];
} elseif (isset($data['checkout_request_id'])) {
$checkout_id = $data['checkout_request_id'];
}
echo "STK Push initiated successfully! Checkout ID: " . $checkout_id;
echo "Please check your phone and enter your M-Pesa PIN to complete payment.";
// Store transaction in your database with status 'pending'
// You will receive a callback at your webhook URL when payment completes
} else {
$error_msg = $data['error'] ?? $data['ResponseDescription'] ?? 'Unknown payment error';
echo 'Payment initiation failed: ' . $error_msg;
}
?>
Integration Example (JavaScript)
const payload = {
client_id: 'codian_prd_j2T2i15dg5',
client_secret: 'codian_sk_prd_FSCzai6tHjad99FBGP34j1fs61sw0N',
amount: 50.00,
phone: '254794335725'
};
fetch('https://api.codian.co.ke/v1/payments/c2b/initiate/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('STK Push initiated! Checkout ID:', data.CheckoutRequestID);
alert('Please check your phone and enter your M-Pesa PIN to complete payment.');
} else {
console.error('Error:', data.error || data.ResponseDescription);
}
})
.catch(error => console.error('Error:', error));
Integration Example (Python)
import requests
import json
payload = {
"client_id": "codian_prd_j2T2i15dg5",
"client_secret": "codian_sk_prd_FSCzai6tHjad99FBGP34j1fs61sw0N",
"amount": 50.00,
"phone": "254794335725"
}
response = requests.post(
"https://api.codian.co.ke/v1/payments/c2b/initiate/",
json=payload,
headers={"Content-Type": "application/json"},
timeout=30
)
if response.status_code == 200:
data = response.json()
if data.get("success"):
print("STK Push initiated! Checkout ID:", data.get("CheckoutRequestID"))
print("Please check your phone and enter your M-Pesa PIN to complete payment.")
else:
print("Error:", data.get("error", data.get("ResponseDescription", "Unknown error")))
else:
print("Request failed with status code:", response.status_code)
Payments API: Managed Integration
Overview
The Managed Integration simplifies the payment process by handling the entire flow, including form rendering and redirects. Developers provide a JSON payload with transaction details and redirect URLs. Codian hosts the payment pages and manages the M-Pesa interaction.
Endpoint URLs
- Sandbox:
https://codian.co.ke/session/checkout/ - Production:
https://codian.co.ke/session/checkout/
Payload Structure
Send a JSON payload to the appropriate endpoint. The payload is compatible with any language supporting HTTP POST requests.
| Field | Type | Description | Example |
|---|---|---|---|
| client_id | string | Your Codian Client ID | codian_prd_0wGSy66bZu |
| client_secret | string | Your Codian Client Secret | codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD |
| amount | number | Amount in KES (min 1) | 100.00 |
| transaction_desc | text | Transaction description | Order #123 |
| success_url | string | Redirect URL on success | https://yourapp.com/success |
| failure_url | string | Redirect URL on failure | https://yourapp.com/failure |
| amount_readonly | boolean (0/1) | Make amount field read-only (optional) | 1 |
| transaction_desc_readonly | boolean (0/1) | Make description read-only (optional) | 0 |
{
"client_id": "codian_prd_0wGSy66bZu",
"client_secret": "codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD",
"amount": 100.00,
"transaction_desc": "Order #123",
"success_url": "https://yourapp.com/success",
"failure_url": "https://yourapp.com/failure",
"amount_readonly": 1,
"transaction_desc_readonly": 0
}
Integration Example
Send the payload to initiate a payment. Codian handles the payment form and redirects.
const payload = {
client_id: 'codian_prd_0wGSy66bZu',
client_secret: 'codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD',
amount: 100.00,
transaction_desc: 'Order #123',
success_url: 'https://yourapp.com/success',
failure_url: 'https://yourapp.com/failure',
amount_readonly: 1
};
fetch('https://codian.co.ke/session/checkout/process.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => {
if (data.success) {
window.location.href = data.redirect_url;
} else {
console.error('Error:', data.error);
}
})
.catch(error => console.error('Error:', error));
Payments API: Webhooks
Webhook Setup (REQUIRED)
IMPORTANT: To receive payment notifications, you must configure a webhook endpoint in your Codian dashboard under the Webhooks tab. Without this, you will not receive any transaction updates.
Configuration Steps:
- Log in to your Codian dashboard
- Navigate to the Webhooks section for your app
- Add a webhook URL (e.g.,
https://yourapp.com/callback.php) - Select the events to receive (recommended: all payment events)
- Save your webhook configuration
- Your endpoint must return HTTP 200 to confirm receipt
Payments API: Callback Payload Structure
What to Expect at Your Webhook
When a payment is completed or fails, Codian sends a callback to your configured webhook URL. Below is the exact JSON payload structure you will receive at your endpoint.
STK Push Callback (Successful Payment)
Sent when the M-Pesa STK Push is completed successfully (ResultCode: 0).
{
"Body": {
"stkCallback": {
"MerchantRequestID": "52fa-4e92-bebd-51f12cb786f3256",
"CheckoutRequestID": "ws_CO_18102025233012373794335725",
"ResultCode": 0,
"ResultDesc": "The service request is processed successfully.",
"CallbackMetadata": {
"Amount": 50,
"MpesaReceiptNumber": "TJIKQ7V33N",
"TransactionDate": "2025-10-18 23:30:26",
"PhoneNumber": 254794335725
}
}
}
}
Failed Payment Callback
Sent when the payment fails (e.g., user cancels, insufficient funds).
{
"Body": {
"stkCallback": {
"MerchantRequestID": "52fa-4e92-bebd-51f12cb786f3256",
"CheckoutRequestID": "ws_CO_18102025233012373794335725",
"ResultCode": 1037,
"ResultDesc": "The service request has been cancelled by the user.",
"CallbackMetadata": {}
}
}
}
Understanding Callback Fields
| Field | Description | Usage |
|---|---|---|
| CheckoutRequestID | Unique identifier for this STK Push request | Use this to match the callback with your pending transaction |
| ResultCode | 0 = Success, any other value = Failure | Check this first to determine payment outcome |
| ResultDesc | Human-readable description of the result | Use for logging and error messages |
| MpesaReceiptNumber | M-Pesa transaction receipt number | Unique reference for the completed transaction |
| Amount | The amount paid | Verify against your expected amount |
| PhoneNumber | Customer's phone number | Identify which user made the payment |
Sample Webhook Handler (PHP)
This example shows how to properly handle the callback at your endpoint. Your script must return HTTP 200.
<?php
// callback.php - Your webhook endpoint
header('Content-Type: application/json');
// Get the raw POST data
$raw_data = file_get_contents('php://input');
$callback_data = json_decode($raw_data, true);
// Validate callback data
if (!isset($callback_data['Body']['stkCallback'])) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'Invalid callback data']);
exit;
}
$stk_callback = $callback_data['Body']['stkCallback'];
$checkout_request_id = $stk_callback['CheckoutRequestID'];
$result_code = $stk_callback['ResultCode'];
$result_desc = $stk_callback['ResultDesc'];
// Log the callback for debugging
error_log("Callback received - CheckoutID: $checkout_request_id, ResultCode: $result_code");
// Connect to your database
require_once 'connect.php';
// Find the pending transaction by checkout_request_id
$stmt = $pdo->prepare("SELECT * FROM mpesa_transactions WHERE checkout_request_id = ?");
$stmt->execute([$checkout_request_id]);
$transaction = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$transaction) {
error_log("Transaction not found for CheckoutID: $checkout_request_id");
http_response_code(200); // Still return 200 to acknowledge receipt
echo json_encode(['success' => true, 'message' => 'Callback received but transaction not found']);
exit;
}
if ($result_code == 0) {
// Payment successful - extract metadata
$metadata = [];
if (isset($stk_callback['CallbackMetadata']['Item'])) {
foreach ($stk_callback['CallbackMetadata']['Item'] as $item) {
$metadata[$item['Name']] = $item['Value'];
}
}
$mpesa_receipt = $metadata['MpesaReceiptNumber'] ?? null;
$amount = $metadata['Amount'] ?? null;
$phone = $metadata['PhoneNumber'] ?? null;
$trans_date = $metadata['TransactionDate'] ?? null;
// Update transaction as completed
$update = $pdo->prepare("
UPDATE mpesa_transactions
SET status = 'completed',
trans_id = ?,
trans_amount = ?,
result_desc = ?,
callback_payload = ?
WHERE checkout_request_id = ?
");
$update->execute([
$mpesa_receipt,
$amount,
$result_desc,
json_encode($callback_data),
$checkout_request_id
]);
// Update user registration status or perform other business logic
// $pdo->prepare("UPDATE users SET is_registered = 1 WHERE id = ?")->execute([$transaction['user_id']]);
error_log("Payment completed for CheckoutID: $checkout_request_id, Receipt: $mpesa_receipt");
} else {
// Payment failed
$update = $pdo->prepare("
UPDATE mpesa_transactions
SET status = 'failed',
result_desc = ?,
callback_payload = ?
WHERE checkout_request_id = ?
");
$update->execute([
$result_desc,
json_encode($callback_data),
$checkout_request_id
]);
error_log("Payment failed for CheckoutID: $checkout_request_id, Reason: $result_desc");
}
// IMPORTANT: Always return HTTP 200 to acknowledge receipt
echo json_encode(['success' => true, 'message' => 'Callback processed successfully']);
?>
Testing Your Webhook
Before going live, test your webhook implementation:
- Use the Codian sandbox environment for all tests
- Configure your webhook URL in the sandbox dashboard
- Initiate test payments using the sandbox endpoints
- Use a tool like webhook.site to inspect raw payloads
- Verify your database updates correctly for both success and failure scenarios
Common test phone numbers for sandbox: 254708374149 (success), 254708374148 (failure)
Chatbots API: Graygle Chatbot Platform
Create intelligent, customizable chatbots for your website with Graygle - our powerful chatbot platform. Use your Codian account to login, build, train, and deploy AI-powered conversational agents in minutes.
Quick Start Guide
Create Your Chatbot
Visit graygle.codian.co.ke and login with your existing Codian account credentials. No separate registration needed!
Customize & Train
Configure your chatbot's personality, responses, and knowledge base. Train it on your specific business data for accurate, contextual conversations.
Publish & Deploy
Once satisfied with your chatbot, click "Publish" to generate your unique script tag - a simple snippet ready to embed in your website.
Add to Your Site
Copy the provided script tag and paste it just before the closing </body> tag of your website. Your chatbot will appear instantly!
<!-- Graygle Chatbot - Your Intelligent Assistant -->
<script src="https://graygle.codian.co.ke/chatbot.js" data-chatbot-id="your-chatbot-id" data-position="bottom-right"></script>
Chatbots API: Programmatic Integration
API Endpoint
For advanced integrations, you can interact with your Graygle chatbot programmatically using our REST API.
POST https://graygle.codian.co.ke/api/v1/chat/send
Payload Structure
| Field | Type | Description | Example |
|---|---|---|---|
| chatbot_id | string | Your Graygle Chatbot ID (found in chatbot dashboard) | chatbot_abc123 |
| client_id | string | Your Codian Client ID | codian_prd_0wGSy66bZu |
| client_secret | string | Your Codian Client Secret | codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD |
| session_id | string | Unique session identifier for conversation continuity | sess_789xyz |
| message | string | User's message to the chatbot | Hi, what's my order status? |
| user_data | object | Optional user metadata for personalization | {"name": "John", "email": "john@example.com"} |
{
"chatbot_id": "chatbot_abc123",
"client_id": "codian_prd_0wGSy66bZu",
"client_secret": "codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD",
"session_id": "sess_789xyz",
"message": "Hi, what's my order status?",
"user_data": {
"name": "Johnte Sam",
"email": "john@example.com"
}
}
Integration Example
Send a message to your Graygle chatbot and receive an immediate response.
fetch('https://graygle.codian.co.ke/api/v1/chat/send', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chatbot_id: 'chatbot_abc123',
client_id: 'codian_prd_0wGSy66bZu',
client_secret: 'codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD',
session_id: 'sess_' + Date.now(),
message: 'What are your business hours?',
user_data: {
name: 'Jane Smith',
email: 'jane@example.com'
}
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('Chatbot response:', data.response);
// Display response in your UI
document.getElementById('chat-response').innerHTML = data.response;
} else {
console.error('Error:', data.error);
}
})
.catch(error => console.error('Error:', error));
Sample Response
{
"success": true,
"response": "Our business hours are Monday-Friday, 9AM-6PM EAT. How can I help you today?",
"session_id": "sess_789xyz",
"timestamp": "2025-10-19T10:03:00Z",
"intent": "business_hours",
"confidence": 0.98
}
Chatbots API: Webhooks & Events
Real-time Chat Events
Configure webhooks in your Graygle dashboard to receive real-time notifications for chat events, user interactions, and conversation analytics.
Event Types
message.received- When a user sends a messagemessage.delivered- When bot response is deliveredconversation.started- New conversation initiatedconversation.ended- Conversation completedfeedback.received- User provides feedback on bot response
Webhook Payload Example
{
"event": "message.received",
"chatbot_id": "chatbot_abc123",
"session_id": "sess_789xyz",
"user_data": {
"name": "Johnte Sam",
"email": "john@example.com",
"ip_address": "192.168.1.1"
},
"message": {
"id": "msg_456",
"text": "Hi, what's my order status?",
"timestamp": "2025-10-19T10:02:30Z"
},
"bot_response": {
"id": "resp_789",
"text": "Please provide your order number.",
"timestamp": "2025-10-19T10:02:31Z",
"processing_time_ms": 850
}
}
Graygle Dashboard Features
- Visual conversation builder
- Intent recognition & NLP
- Custom knowledge base training
- Multi-language support
- Analytics dashboard
- Human handoff capability
- Custom styling & branding
- API access for advanced use
Emails API: Overview
The Emails API supports sending transactional or bulk emails with customizable templates. JSON payloads enable seamless integration.
Emails API: Integration
Payload Structure
Send a JSON payload to https://codian.co.ke/api/emails/send.
| Field | Type | Description | Example |
|---|---|---|---|
| client_id | string | Your Codian Client ID | codian_prd_0wGSy66bZu |
| client_secret | string | Your Codian Client Secret | codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD |
| recipient | string | Recipient email address | user@example.com |
| subject | text | Email subject | Your Order Confirmation |
| body | text | Email content (HTML or plain) | <p>Thanks for your order!</p> |
{
"client_id": "codian_prd_0wGSy66bZu",
"client_secret": "codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD",
"recipient": "user@example.com",
"subject": "Your Order Confirmation",
"body": "<p>Thanks for your order!</p>"
}
Integration Example
Send an email using this JavaScript example.
fetch('https://codian.co.ke/api/emails/send', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_id: 'codian_prd_0wGSy66bZu',
client_secret: 'codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD',
recipient: 'user@example.com',
subject: 'Your Order Confirmation',
body: '<p>Thanks for your order!</p>'
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('Email sent!');
} else {
console.error('Error:', data.error);
}
})
.catch(error => console.error('Error:', error));
Emails API: Webhooks
Webhook Payload
Receive email delivery status via your webhook endpoint.
{
"email_id": "email_789",
"recipient": "user@example.com",
"status": "delivered",
"timestamp": "2025-10-19 10:03:00"
}
SMS API: Overview
The SMS API enables sending notifications or campaigns to users via SMS. JSON payloads ensure compatibility with any platform.
SMS API: Integration
Payload Structure
Send a JSON payload to https://codian.co.ke/api/sms/send.
| Field | Type | Description | Example |
|---|---|---|---|
| client_id | string | Your Codian Client ID | codian_prd_0wGSy66bZu |
| client_secret | string | Your Codian Client Secret | codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD |
| phone_number | string | Recipient phone (e.g., 2547XXXXXXXX) | 254794335725 |
| message | text | SMS content (max 160 chars) | Your order #123 is shipped! |
{
"client_id": "codian_prd_0wGSy66bZu",
"client_secret": "codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD",
"phone_number": "254794335725",
"message": "Your order #123 is shipped!"
}
Integration Example
Send an SMS using this Python example.
import requests
payload = {
"client_id": "codian_prd_0wGSy66bZu",
"client_secret": "codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD",
"phone_number": "254794335725",
"message": "Your order #123 is shipped!"
}
response = requests.post("https://codian.co.ke/api/sms/send", json=payload)
if response.status_code == 200:
data = response.json()
if data["success"]:
print("SMS sent!")
else:
print("Error:", data["error"])
else:
print("Request failed:", response.status_code)
SMS API: Webhooks
Webhook Payload
Receive SMS delivery status via your webhook endpoint.
{
"sms_id": "sms_101",
"phone_number": "254794335725",
"status": "delivered",
"timestamp": "2025-10-19 10:03:00"
}
Airtime API: Overview
The Airtime API enables mobile airtime top-ups for users across supported networks. JSON payloads ensure seamless integration.
Airtime API: Integration
Payload Structure
Send a JSON payload to https://codian.co.ke/api/airtime/send.
| Field | Type | Description | Example |
|---|---|---|---|
| client_id | string | Your Codian Client ID | codian_prd_0wGSy66bZu |
| client_secret | string | Your Codian Client Secret | codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD |
| phone_number | string | Recipient phone (e.g., 2547XXXXXXXX) | 254794335725 |
| amount | number | Airtime amount in KES | 50.00 |
{
"client_id": "codian_prd_0wGSy66bZu",
"client_secret": "codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD",
"phone_number": "254794335725",
"amount": 50.00
}
Integration Example
Top up airtime using this JavaScript example.
fetch('https://codian.co.ke/api/airtime/send', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_id: 'codian_prd_0wGSy66bZu',
client_secret: 'codian_sk_prd_21FjoE6JA6uNfSfrfvRtJ8MtRlxWiD',
phone_number: '254794335725',
amount: 50.00
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('Airtime top-up sent!');
} else {
console.error('Error:', data.error);
}
})
.catch(error => console.error('Error:', error));
Airtime API: Webhooks
Webhook Payload
Receive airtime top-up status via your webhook endpoint.
{
"airtime_id": "airtime_202",
"phone_number": "254794335725",
"amount": 50.00,
"status": "completed",
"timestamp": "2025-10-19 10:03:00"
}
Common Errors
Error Codes & Solutions
Below are common errors and their solutions.
| Error Code | Description | Solution |
|---|---|---|
| 401 Unauthorized | Invalid client_id or client_secret. |
Verify credentials in your Codian dashboard. Ensure no spaces or typos. Use environment variables to avoid hardcoding errors. |
| 400 Bad Request | Missing or invalid payload fields. | Check payload against the API's required fields (e.g., amount ≥ 1, valid phone_number). Log the request body for debugging. |
| 1037 | Transaction cancelled by user | User did not enter PIN or cancelled the STK Push. This is a normal user action, handle gracefully. |
| 1032 | Transaction failed - insufficient funds | User does not have enough money in their M-Pesa account. Prompt them to try again with sufficient funds. |
| Timeout | Payment or API request timed out. | Ensure user has funds (for payments) or network is stable. Implement retry logic with exponential backoff. |
| 503 Service Unavailable | Codian server is temporarily down or under maintenance. | Check Codian status page for updates. Retry after some time. |
Contact Support
Support Channels
For assistance, contact our support team via:
- Email: support@codian.co.ke
- Dashboard: Submit a ticket from your Codian dashboard.
- Community: Join our developer community at codian.co.ke/community.
Include your client_id, error details, and logs for faster resolution.