Download App

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

  1. Normalize the customer WhatsApp number before calling the API.
  2. Confirm customer intent before creating any order.
  3. Show the calculated total before submission.
  4. Store returned type, id, and reference in the bot conversation state.
  5. Send payment_url only when the API returns one.
  6. Request exam ZIP links only for paid or approved softcopy exam orders.
  7. Request a fresh ZIP link when an older link has expired.
  8. Hand off to a human agent for disputes, unclear payments, or repeated server errors.

Recommended Bot Flows

Track Order

  1. User asks to track an order.
  2. Bot calls POST /orders/track using the sender WhatsApp number.
  3. Bot summarizes newest orders by label, status, amount, and date.
  4. If the customer selects an order, bot calls GET /orders/{type}/{id}.

Place New Order

  1. Bot calls GET /catalog to confirm available products and pricing.
  2. Bot collects required customer, school, delivery, and quantity fields.
  3. Bot repeats the final summary and total.
  4. After confirmation, bot calls POST /orders.
  5. Bot sends the returned order reference and payment link when available.

Deliver Paid Exams

  1. Bot tracks the customer's orders.
  2. Bot finds an approved softcopy_exam order.
  3. Bot calls POST /download-links/exam-order.
  4. 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_KEY when 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

  1. Health endpoint returns status: ok.
  2. Invalid API key returns 401.
  3. Order tracking works with 070..., 25670..., and +25670... formats.
  4. Each supported order type can be created from a confirmed bot conversation.
  5. Pending orders include a usable payment link where applicable.
  6. Approved softcopy exam orders return a download link.
  7. Download links work immediately and fail after 24 hours.
  8. The bot hands off gracefully when the API returns validation or server errors.