Codian Logo API Documentation
CODIAN API DOCUMENTATION
Codian → APIs → Payments | Chatbots | Emails | SMS | Airtime

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:

Custom Integration (Both Sandbox & Production)

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
View Documentation →
Managed Integration (For Production apps only)

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
View Documentation →
Important: For both integration methods, you must configure a webhook endpoint in your Codian dashboard to receive transaction updates.This is not mandatory if you wont be collecting the responses but without a properly configured webhook, you will not receive payment confirmations.

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"
}
Note: The phone number can be in format 0712345678 or 254712345678. The API handles both formats automatically.

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)
Note: After initiating STK Push, the user receives an M-Pesa prompt on their phone. Transaction updates are sent to the webhook endpoint you configured in the Codian dashboard. Your application must store the pending transaction and update its status when you receive the callback.

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));
Note:Managed Itegration wotks with production apps only. Even with Managed Integration, you'll receive transaction updates via webhooks if you set them. This is important if you want to save transactions to your app's database.

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:

  1. Log in to your Codian dashboard
  2. Navigate to the Webhooks section for your app
  3. Add a webhook URL (e.g., https://yourapp.com/callback.php)
  4. Select the events to receive (recommended: all payment events)
  5. Save your webhook configuration
  6. Your endpoint must return HTTP 200 to confirm receipt
Important: Test your webhook in the sandbox environment to verify payload handling before going live. The webhook URL must be publicly accessible (not localhost) for production use.

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']);
?>
Remember: Your webhook endpoint must always return HTTP 200 (even for failed transactions) to confirm receipt. If you don't return 200, Codian will retry the callback.

Testing Your Webhook

Before going live, test your webhook implementation:

  1. Use the Codian sandbox environment for all tests
  2. Configure your webhook URL in the sandbox dashboard
  3. Initiate test payments using the sandbox endpoints
  4. Use a tool like webhook.site to inspect raw payloads
  5. 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

Introducing Graygle Chatbots!

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

Step 1

Create Your Chatbot

Visit graygle.codian.co.ke and login with your existing Codian account credentials. No separate registration needed!

Step 2

Customize & Train

Configure your chatbot's personality, responses, and knowledge base. Train it on your specific business data for accurate, contextual conversations.

Step 3

Publish & Deploy

Once satisfied with your chatbot, click "Publish" to generate your unique script tag - a simple snippet ready to embed in your website.

Step 4

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!

Example Graygle Chatbot Script Tag
<!-- 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>
One account, multiple chatbots: You can create and manage multiple chatbots for different websites or purposes under a single Codian account.

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 message
  • message.delivered - When bot response is delivered
  • conversation.started - New conversation initiated
  • conversation.ended - Conversation completed
  • feedback.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
    }
}
Pro Tip: Use webhook events to track conversation analytics, store chat history, or trigger follow-up actions in your own systems.

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:

Include your client_id, error details, and logs for faster resolution.