Developer Documentation
Support API for WhatsApp Agent Bot
Use this API to connect a WhatsApp support agent to E-Learn Uganda for order tracking, order placement, schedules, catalog lookup, payment links, and 24-hour exam ZIP download links.
Setup
Set strong secrets in the web app environment. The WhatsApp bot keeps the API key on its backend only.
SUPPORT_API_KEY=use-a-long-random-secret
SUPPORT_DOWNLOAD_SECRET=use-a-different-long-random-secret
Every protected request must include these headers:
Authorization: Bearer use-a-long-random-secret
Content-Type: application/json
Accept: application/json
The customer should never see the API key. Customers only receive signed download URLs generated by the API.
Bot Integration Rules
- Normalize the customer WhatsApp number before calling the API.
- Confirm customer intent before creating any order.
- Show the calculated total before submission.
- Store returned
type,id, andreferencein the bot conversation state. - Send
payment_urlonly when the API returns one. - Request exam ZIP links only for paid or approved softcopy exam orders.
- Request a fresh ZIP link when an older link has expired.
- Hand off to a human agent for disputes, unclear payments, or repeated server errors.
Recommended Bot Flows
Track Order
- User asks to track an order.
- Bot calls
POST /orders/trackusing the sender WhatsApp number. - Bot summarizes newest orders by label, status, amount, and date.
- If the customer selects an order, bot calls
GET /orders/{type}/{id}.
Place New Order
- Bot calls
GET /catalogto confirm available products and pricing. - Bot collects required customer, school, delivery, and quantity fields.
- Bot repeats the final summary and total.
- After confirmation, bot calls
POST /orders. - Bot sends the returned order reference and payment link when available.
Deliver Paid Exams
- Bot tracks the customer's orders.
- Bot finds an approved
softcopy_examorder. - Bot calls
POST /download-links/exam-order. - Bot sends the returned link and explains that it expires in 24 hours.
Endpoints
GET /api/support/health
Returns service status, server time, and timezone.
GET /api/support/catalog
Returns current exams, question banks, softcopy holiday packages, and print pricing.
GET /api/support/schedules
Returns support hours, contact details, and delivery status wording.
POST /api/support/orders/track
{
"phone": "0700000000",
"limit": 10
}
GET /api/support/orders/{type}/{id}
Supported types are hardcopy, holiday, book_cover, p7_program, question_bank, softcopy_exam, and softcopy_holiday.
POST /api/support/orders
Create hardcopy, holiday, book cover, P.7 program, or question bank orders.
| Order Type | Required Fields |
|---|---|
| hardcopy | type, order_category, school_name, school_contact, position, whatsapp_number, region, address, at least one class quantity |
| holiday | type, term, school_name, school_contact, position, whatsapp_number, region, address, at least one class quantity |
| book_cover | type, school_name, school_contact, position, whatsapp_number, region, address, small or big |
| p7_program | type, order_category, school_name, school_contact, customer_name, whatsapp_number, region, address, normal_qty or white_qty |
| question_bank | type, name, customer_phone, address, items |
POST /api/support/download-links/exam-order
{
"order_id": 123
}
Returns a random signed URL that expires after 24 hours. Only approved or paid softcopy exam orders can receive a link.
Sample Payloads
Create Hardcopy Order
{
"type": "hardcopy",
"order_category": "Beginning of Term I",
"school_name": "Demo Primary School",
"school_contact": "0700000000",
"position": "Director",
"whatsapp_number": "0700000000",
"region": "Kampala",
"address": "School address",
"p1": 30,
"p2": 30
}
Create P.7 Program Order
{
"type": "p7_program",
"order_category": "National Special Mock 2026",
"school_name": "Demo Primary School",
"school_contact": "0700000000",
"customer_name": "Jane",
"whatsapp_number": "0700000000",
"region": "Kampala",
"address": "School address",
"white_qty": 20,
"marking": true
}
Node.js Client
const API_BASE_URL = process.env.ELEARN_SUPPORT_API_URL;
const API_KEY = process.env.ELEARN_SUPPORT_API_KEY;
async function supportApi(path, options = {}) {
const response = await fetch(`${API_BASE_URL}${path}`, {
...options,
headers: {
Authorization: `Bearer ${API_KEY}`,
Accept: "application/json",
"Content-Type": "application/json",
...(options.headers || {})
}
});
const data = await response.json().catch(() => ({}));
if (!response.ok) {
throw new Error(data.message || data.error || `Support API failed: ${response.status}`);
}
return data;
}
async function trackCustomerOrders(whatsappNumber) {
return supportApi("/orders/track", {
method: "POST",
body: JSON.stringify({ phone: whatsappNumber, limit: 5 })
});
}
async function createExamDownloadLink(orderId) {
return supportApi("/download-links/exam-order", {
method: "POST",
body: JSON.stringify({ order_id: orderId })
});
}
PHP Client
function supportApi(string $path, array $payload = null, string $method = 'GET'): array
{
$baseUrl = getenv('ELEARN_SUPPORT_API_URL');
$apiKey = getenv('ELEARN_SUPPORT_API_KEY');
$ch = curl_init($baseUrl . $path);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_TIMEOUT => 30,
]);
if ($payload !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
}
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode((string) $body, true) ?: [];
if ($status < 200 || $status >= 300) {
throw new RuntimeException($data['message'] ?? $data['error'] ?? 'Support API request failed.');
}
return $data;
}
Security Checklist
- Use HTTPS in production.
- Keep API keys only in server-side environment variables.
- Rotate
SUPPORT_API_KEYwhen a bot vendor or hosting environment changes. - Do not log full download URLs because they contain temporary access tokens.
- Do not create an order until the customer confirms the final summary.
- Do not create download links for pending or rejected orders.
- Rate-limit bot calls at the bot layer to prevent spam.
Production Testing Checklist
- Health endpoint returns
status: ok. - Invalid API key returns
401. - Order tracking works with
070...,25670..., and+25670...formats. - Each supported order type can be created from a confirmed bot conversation.
- Pending orders include a usable payment link where applicable.
- Approved softcopy exam orders return a download link.
- Download links work immediately and fail after 24 hours.
- The bot hands off gracefully when the API returns validation or server errors.