KHOLO LogoDocs v1.0
Integrations

Sage 200 Evolution ERP Integration

Freedom Service REST SDK, Agent permissions, and idempotency key mapping.

This guide describes how to connect KHOLO to Sage 200 Evolution (and Sage Pastel Partner) using the official Freedom Service REST API SDK.


1. Integration Architecture

Sage 200 Evolution Gateway BridgePort 8080 REST SDK
Cloud SideFastify

Kholo Backend & ERP Adapter

Translates verified order lines, assigns order.id as the idempotency key, and dispatches JSON payload.

Distributor On-PremiseFreedom SDK

Sage Freedom Service & SQL

Creates Sales Order (SO-2026-XXXX), reserves warehouse inventory, and enforces customer credit limits.


2. Prerequisites & Server Setup

Before configuring Kholo, ensure the distributor's IT team has configured:

  1. Sage Freedom Service REST API: Installed on the Sage application server and listening on an accessible port (default 8080).
  2. Dedicated Agent Account: Create an Evolution Agent named kholo_agent with:
    • Sales Order Entry permissions (POST /SalesOrder).
    • Read access to Customer Master (GET /Customer) and Inventory Master (GET /Inventory).
  3. Firewall / VPN: Secure the Freedom Service port so that only Kholo's static outbound IP addresses can communicate with it.

3. Configuring the ERP Connection in Kholo

In the Kholo web portal, navigate to Settings $\rightarrow$ ERP Configuration or update the erpConfig JSON in the Tenant database record:

{
  "type": "sage_evolution",
  "endpoint": "http://192.168.X.X:8080/Freedom.Core/METRO_DB/SDK/Rest",
  "branchCode": "001",
  "warehouseCode": "001",
  "agentCode": "kholo_agent",
  "agentPassword": "EncryptedPasswordHere",
  "idempotencyKey": "ExternalOrderNo"
}

4. Sales Order REST Payload Structure

When an order is approved, SageEvolutionConnector constructs and posts the following payload:

{
  "Header": {
    "CustomerAccount": "CUST-8832",
    "ExternalOrderNo": "997220b1-3d2e-4fad-a758-fb0fe872aeb0",
    "OrderDate": "2026-09-30",
    "DeliveryAddress": {
      "CustomerName": "Clerk (KwaMashu Spaza)",
      "ContactPhone": "+27 00 000 0000"
    },
    "BranchCode": "001",
    "Source": "Kholo WhatsApp Middleware",
    "Notes": "Automated WhatsApp Order: 10 whites 12.5kg, 4 tastic 10kg"
  },
  "Lines": [
    {
      "LineNumber": 1,
      "ItemCode": "WSTAR-12.5KG",
      "Description": "White Star Maize Meal 12.5kg",
      "Quantity": 10,
      "UnitPrice": 148.50,
      "TaxType": 2,
      "WarehouseCode": "001"
    },
    {
      "LineNumber": 2,
      "ItemCode": "TASTIC-10KG",
      "Description": "Tastic Parboiled Rice 10kg",
      "Quantity": 4,
      "UnitPrice": 215.00,
      "TaxType": 2,
      "WarehouseCode": "001"
    }
  ]
}

5. Strict Idempotency Handling

To prevent duplicate sales orders caused by network retries, connection drops, or multiple clerk clicks:

  1. ExternalOrderNo Mapping: Kholo assigns its internal UUID (order.id) to ExternalOrderNo in Sage Evolution.
  2. Pre-Flight Duplicate Check: If order.erpSalesOrderId already exists on the Kholo order, the system skips the HTTP call and returns the existing order reference immediately:
    if (order.erpSalesOrderId) {
      return {
        success: true,
        erpSalesOrderId: order.erpSalesOrderId,
        idempotent: true
      };
    }
  3. Database Conflict Resolution: Sage Freedom Service rejects any secondary request containing an existing ExternalOrderNo, returning the original order reference.

6. Verifying the Connection (Smoke Test)

You can verify communication with the Sage Evolution instance from the command line:

cd apps/api
npx ts-node src/scripts/verify-readiness.ts

Expected confirmation:

[CHECK 5/6] Sage ERP & Pick Slip:  PASS (SO Format: SO-2026-XXXX, Pick Slip: 3 lines)

On this page