Sales Order Module

SKYBIZ API — Sales Order Module

Sales Order

The Sales Order module allows you to retrieve and create sales order records in your SKYBIZ account. Supports both read and create operations.

Endpoint: /apiv2/modules/sales_order.php

Required Permissions: Sales Order — Read, Sales Order — Create

Allowed DocType: SO (Sales Order only)


Read Sales Orders

Retrieves sales orders created within the given date range. Returns all fields — no field filtering or custom filters are supported for this module.

Base Request Structure

{
  "api_key": "your-api-key",
  "api_secret": "your-api-secret",
  "action": "read",
  "date_from": "YYYY-MM-DD",
  "date_to": "YYYY-MM-DD"
}

Request Parameters

Parameter Description Required
api_key Your API key Yes
api_secret Your API secret Yes
action Must be "read" Yes
date_from Start date (YYYY-MM-DD) Yes
date_to End date (YYYY-MM-DD). Max 31 days range. Yes

Date Rules

  • Format must be YYYY-MM-DD — e.g. "2026-04-01"
  • Maximum range is 31 days
  • date_from cannot be after date_to

Available Fields (Read Only)

The Sales Order module returns all fields. Field filtering is not supported for this module.

Field Type Description
Doc1No string Document number (identifier)
Doc2No / Doc3No string Reference document numbers
D_ate string Document date
CusCode string Customer code
CusName string Customer name
CurCode string Currency code (e.g., RM, SGD, USD)
CurRate1 float Exchange rate
TermCode integer Payment term in days
HCNetAmt float Net amount before tax
HCDtTax float Total tax amount
DocType string Document type — always "SO"
Status string Order status — "Waiting", "Completed", etc.
Address / City / State / Zip string Delivery address components
ContactTel / Email string Contact telephone and email
Attention string Attention note / special remarks
ItemCode string Item code
Description / Description2 string Item description lines
Qty float Quantity ordered
FactorQty float UOM conversion factor (usually 1)
UOM string Unit of measure
UOMSingular string Singular form of UOM
HCUnitCost float Unit cost
HCLineAmt float Line total amount
HCTax float Tax amount for the line
TaxRate1 float Tax rate in percent
DetailTaxCode string Tax code
BlankLine string Line type — "0" Stock Item, "4" Other Charge, "6" GL Account
DeliveryDate string Expected delivery date

Example 1 — Get All Sales Orders (All Fields)

This request returns all sales order fields for orders created between April 1, 2026 and April 30, 2026.

Request

{
  "api_key": "your-api-key",
  "api_secret": "your-api-secret",
  "action": "read",
  "date_from": "2026-04-01",
  "date_to": "2026-04-30"
}

Sample Code for making an API READ request using php

<?php
header('Content-Type: application/json');

// ============================================================
// STEP 1: CONFIGURATION
// ============================================================

$API_KEY = "your-api-key";
$API_SECRET = "your-api-secret";
$ACTION = "read";

// Date range (required for all endpoints, max 31 days)
$DATE_FROM = "2026-04-01";
$DATE_TO = "2026-04-30";

// ============================================================
// STEP 2: ENDPOINT
// ============================================================

$BASE_URL = "https://domain-name/01/clientportal/apiv2/modules"; //(replace it with your skybiz domain name url)
$ENDPOINT = "sales_order.php";

// ============================================================
// STEP 3: REQUEST PARAMETERS
// ============================================================

$requestParams = [
    "date_from" => $DATE_FROM,
    "date_to" => $DATE_TO
];

// ============================================================
// STEP 4: BUILD PAYLOAD
// ============================================================

$payload = array_merge(
    [
        "api_key" => $API_KEY,
        "api_secret" => $API_SECRET,
        "action" => $ACTION
    ],
    $requestParams
);

// ============================================================
// STEP 5: SEND REQUEST
// ============================================================

$url = rtrim($BASE_URL, '/') . '/' . ltrim($ENDPOINT, '/');

$ch = curl_init($url);

curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query($payload),
    CURLOPT_TIMEOUT => 30,
]);

$response = curl_exec($ch);

// ============================================================
// STEP 6: HANDLE CURL ERROR
// ============================================================

if ($response === false) {
    echo json_encode([
        "status" => "error",
        "timestamp" => date("c"),
        "request_id" => uniqid("req_"),
        "message" => curl_error($ch)
    ], JSON_PRETTY_PRINT);
    curl_close($ch);
    exit;
}

$httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// ============================================================
// STEP 7: DECODE RESPONSE
// ============================================================

$result = json_decode($response, true);

if (!$result) {
    echo json_encode([
        "status" => "error",
        "timestamp" => date("c"),
        "request_id" => uniqid("req_"),
        "message" => "Invalid JSON from API",
        "raw_response" => $response
    ], JSON_PRETTY_PRINT);
    exit;
}

// ============================================================
// STEP 8: RETURN CLEAN JSON FORMAT
// ============================================================

echo json_encode([
    "status" => $result['status'] ?? "error",
    "timestamp" => date("c"),
    "request_id" => $result['request_id'] ?? uniqid("req_"),
    "data" => $result['data'] ?? null,
    "message" => $result['message'] ?? null
], JSON_PRETTY_PRINT);

Response (Success)

{
  "status": "response",
  "timestamp": "2026-04-30T04:07:04+00:00",
  "request_id": "req_69f2d56891e57",
  "data": {
    "requested_by": "your-api-key",
    "mode": "2",
    "date_range": {
      "from": "2026-04-01",
      "to": "2026-04-30",
      "days": 30
    },
    "total_returned": 2,
    "data": [
      {
        "Doc1No": "SO-001",
        "CusCode": "CUST001",
        "CusName": "Acme Sdn Bhd",
        "CurCode": "RM",
        "HCNetAmt": 1500.00,
        "Status": "Waiting",
        "D_ate": "2026-04-15",
        "DateTimeModified": "2026-04-15 10:30:00"
      },
      {
        "Doc1No": "SO-002",
        "CusCode": "CUST002",
        "CusName": "Tech Solutions",
        "CurCode": "RM",
        "HCNetAmt": 2500.00,
        "Status": "Completed",
        "D_ate": "2026-04-20",
        "DateTimeModified": "2026-04-20 14:45:00"
      }
    ]
  }
}

Postman Steps — READ Request

  1. Set method to POST

2. Enter URL: https://your-domain/01/clientportal/apiv2/modules/sales_order.php

3. Set header: Content-Type: application/json

4. Under Body, select raw and format JSON

5. Paste your request payload and click Send


Create Sales Order

Creates one or more sales order records. All documents are validated before any are saved. If any document fails, the entire batch is rejected.

Compulsory Fields — Header

Field Type Description
Doc1No string Unique document number. Must not already exist.
CusCode string Customer code. Must exist in SKYBIZ.
DocType string Must be "SO"
HCNetAmt float Net amount before tax. Must equal sum of all item HCLineAmt.
HCDtTax float Total tax amount. Must equal sum of all item HCTax.

Compulsory Fields — Items

Field Type Description
ItemCode string Item code. Must exist in SKYBIZ.
Description string Item description
Qty float Quantity. Must be greater than 0.
FactorQty float UOM conversion factor. Usually same as Qty. Must be greater than 0.
UOM string Unit of measure. Must exist in SKYBIZ UOM table.
HCUnitCost float Unit price. Must be greater than 0 for stock items.
HCLineAmt float Line total. Must equal Qty × HCUnitCost.
BlankLine string Line type — "0" Stock Item, "4" Other Charge, "6" GL Account

Optional Fields — Header

Field Type Description
Doc2No / Doc3No string Reference document numbers
D_ate string Document date in YYYY-MM-DD format. Defaults to today.
CusName string Customer name (for display on the order)
CurCode string Currency code. Default: MYR
CurRate1 float Exchange rate. Default: 1
Address string Delivery address (Max length is 255 characters)
City / State / Zip string Delivery city, state, postcode
ContactTel / Email string Delivery contact telephone and email
Attention string Attention note or special remarks

Optional Fields — Items

Field Type Description
Description2 string Second description line (Max length is 255 characters)
UOMSingular string Singular form of UOM (auto-populated if empty)
HCDiscount / DisRate1 float Discount amount and discount rate (%)
HCTax float Tax amount for this line. Must equal HCLineAmt × (TaxRate1 / 100).
TaxRate1 float Tax rate in percent — e.g. 6
DetailTaxCode string Tax code. If provided, must exist in SKYBIZ.
SalesPersonCode string Sales Person Code. If provided, must exist in SKYBIZ.
BranchCode / DepartmentCode / ProjectCode string Branch, department, and project codes. If provided, must exist in SKYBIZ.
LocationCode string Stock location code. If provided, must exist in SKYBIZ.
DeliveryDate string Expected delivery date in YYYY-MM-DD format
DUD1 to DUD6 string User-defined detail fields 1 through 6 (Max length is 40 characters)
LineNo integer Line sequence number. Auto-assigned if omitted.

BlankLine Values

Value Type
"0" Stock Item
"4" Other Charge
"6" GL Account

Base Create Request Structure

{
  "api_key": "your-api-key",
  "api_secret": "your-api-secret",
  "action": "create",
  "order_data": {
    "documents": [
      {
        "Doc1No": "SO-001",
        "CusCode": "CUST001",
        "DocType": "SO",
        "D_ate": "2026-05-20",
        "HCNetAmt": 550.00,
        "HCDtTax": 44.00,
        "CurCode": "RM",
        "CurRate1": 1,
        "CusName": "Acme Sdn Bhd",
        "Address": "123 Jalan SS2",
        "City": "Petaling Jaya",
        "State": "Selangor",
        "Zip": "47300",
        "ContactTel": "0123456789",
        "Email": "customer@test.com",
        "Attention": "Urgent order",
        "items": [
          {
            "ItemCode": "ITEM001",
            "Description": "Product A",
            "Qty": 10,
            "FactorQty": 1,
            "UOM": "Piece",
            "HCUnitCost": 50.00,
            "HCLineAmt": 500.00,
            "BlankLine": "0",
            "HCTax": 40.00,
            "TaxRate1": 8,
            "DeliveryDate": "2026-05-25",
            "LineNo": 1
          }
        ]
      }
    ]
  }
}

Sample Code for making an API CREATE request using php

<?php
header('Content-Type: application/json');

// ============================================================
// STEP 1: CONFIGURATION
// ============================================================

$API_KEY = "your-api-key";
$API_SECRET = "your-api-secret";
$ACTION = "create";

// ============================================================
// STEP 2: ENDPOINT
// ============================================================

$BASE_URL = "https://domain-name/01/clientportal/apiv2/modules"; //(replace it with your skybiz domain name url)
$ENDPOINT = "sales_order.php";

// ============================================================
// STEP 3: DATA KEY
// ============================================================

$DATA_KEY = "order_data";

// ============================================================
// STEP 4: BUILD YOUR DOCUMENTS ARRAY
// ============================================================

$DOCUMENTS = [];

// --- Sales Order example ---
$DOCUMENTS[] = [
    "Doc1No" => "SO-001",
    "CusCode" => "CUST001",
    "DocType" => "SO",
    "D_ate" => "2026-05-20",
    "HCNetAmt" => 550.00,
    "HCDtTax" => 44.00,
    "CurCode" => "RM",
    "CurRate1" => 1,
    "CusName" => "Acme Sdn Bhd",
    "Address" => "123 Jalan SS2",
    "City" => "Petaling Jaya",
    "State" => "Selangor",
    "Zip" => "47300",
    "ContactTel" => "0123456789",
    "Email" => "customer@test.com",
    "Attention" => "Urgent order",
    "items" => [
        [
            "ItemCode" => "ITEM001",
            "Description" => "Product A",
            "Qty" => 10,
            "FactorQty" => 1,
            "UOM" => "Piece",
            "HCUnitCost" => 50.00,
            "HCLineAmt" => 500.00,
            "BlankLine" => "0",
            "HCTax" => 40.00,
            "TaxRate1" => 8,
            "DeliveryDate" => "2026-05-25",
            "LineNo" => 1
        ]
    ]
];

// ============================================================
// STEP 5: CLIENT-SIDE COUNT CHECK (Please do not modify this)
// ============================================================

$totalDocuments = 0;

foreach ($DOCUMENTS as $document) {
    $totalDocuments++;

    if (empty($document['Doc1No'])) {
        echo json_encode([
            "status" => "REJECTED_BY_CLIENT",
            "timestamp" => date("c"),
            "request_id" => uniqid("req_"),
            "message" => "CLIENT-SIDE REJECTION: Document at position {$totalDocuments} has empty Doc1No",
            "action_required" => "Fix the document before sending to server"
        ], JSON_PRETTY_PRINT);
        exit;
    }
}

if ($totalDocuments > 500) {
    echo json_encode([
        "status" => "REJECTED_BY_CLIENT",
        "timestamp" => date("c"),
        "request_id" => uniqid("req_"),
        "message" => "CLIENT-SIDE REJECTION: You have {$totalDocuments} documents. Maximum is 500.",
        "your_document_count" => $totalDocuments,
        "max_allowed" => 500,
        "action_required" => "Reduce your documents to 500 or less BEFORE sending to server"
    ], JSON_PRETTY_PRINT);
    exit;
}

echo "=== CLIENT-SIDE VALIDATION ===\n";
echo "Looped through all {$totalDocuments} documents one by one\n";
echo "All documents passed client validation\n";
echo "Document count: {$totalDocuments} (max 500)\n";
echo "Sending to server...\n\n";

// ============================================================
// STEP 6: SEND REQUEST
// ============================================================

$url = rtrim($BASE_URL, '/') . '/' . ltrim($ENDPOINT, '/');

$payload = [
    "api_key" => $API_KEY,
    "api_secret" => $API_SECRET,
    "action" => $ACTION,
    $DATA_KEY => ["documents" => $DOCUMENTS]
];

$ch = curl_init($url);

curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_TIMEOUT => 120,
]);

$response = curl_exec($ch);

// ============================================================
// STEP 7: HANDLE CURL ERROR
// ============================================================

if ($response === false) {
    echo json_encode([
        "status" => "error",
        "timestamp" => date("c"),
        "request_id" => uniqid("req_"),
        "message" => curl_error($ch)
    ], JSON_PRETTY_PRINT);
    curl_close($ch);
    exit;
}

$httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// ============================================================
// STEP 8: DECODE RESPONSE
// ============================================================

$result = json_decode($response, true);

if (!$result) {
    echo json_encode([
        "status" => "error",
        "timestamp" => date("c"),
        "request_id" => uniqid("req_"),
        "message" => "Invalid JSON from API",
        "raw_response" => $response
    ], JSON_PRETTY_PRINT);
    exit;
}

// ============================================================
// STEP 9: RETURN CLEAN JSON FORMAT
// ============================================================

echo "=== SERVER RESPONSE ===\n";
echo json_encode([
    "status" => $result['status'] ?? "error",
    "timestamp" => date("c"),
    "request_id" => $result['request_id'] ?? uniqid("req_"),
    "data" => $result['data'] ?? null,
    "message" => $result['message'] ?? null
], JSON_PRETTY_PRINT);

Response (Success)

{
  "status": "response",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_69fc0070d83cf",
  "data": {
    "requested_by": "your-api-key",
    "mode": "2",
    "summary": {
      "total_documents": 1,
      "inserted": 1,
      "failed": 0
    },
    "successful_documents": ["SO-001"],
    "failed_documents": [],
    "fail_details": {
      "compulsory_fields_missing": [],
      "duplicate_documents": [],
      "invalid_customers": [],
      "invalid_items": [],
      "invalid_tax_codes": [],
      "invalid_sales_persons": [],
      "invalid_locations": [],
      "invalid_departments": [],
      "invalid_projects": [],
      "invalid_branches": [],
      "invalid_currencies": [],
      "invalid_uoms": [],
      "amount_mismatch": [],
      "validation_errors": []
    }
  }
}

Response (Error — Duplicate Document)

{
  "status": "response",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_69fc03e446a20",
  "data": {
    "requested_by": "your-api-key",
    "mode": "2",
    "summary": {
      "total_documents": 1,
      "inserted": 0,
      "failed": 1
    },
    "successful_documents": [],
    "failed_documents": ["SO-001"],
    "fail_details": {
      "duplicate_documents": ["SO-001"],
      "invalid_currencies": [],
      "invalid_uoms": [],
      "amount_mismatch": [],
      "validation_errors": []
    }
  }
}

Error Responses

Missing Date Range (READ)

{
  "status": "error",
  "timestamp": "2026-04-07T10:46:15+08:00",
  "request_id": "req_6612f3b9c21a7",
  "message": "date_from and date_to are required"
}

Invalid DocType (CREATE)

{
  "status": "error",
  "timestamp": "2026-04-07T10:46:15+08:00",
  "request_id": "req_6612f3b9c21a7",
  "message": "Invalid DocType 'XXX'. Allowed: SO"
}

Missing Compulsory Fields (CREATE)

{
  "status": "response",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_123456",
  "data": {
    "summary": {
      "total_documents": 1,
      "inserted": 0,
      "failed": 1
    },
    "failed_documents": ["SO-001"],
    "fail_details": {
      "compulsory_fields_missing": [
        "Document 1 (Doc1No: SO-001): Missing header fields - CusCode, HCNetAmt, HCDtTax, DocType"
      ]
    }
  }
}

Invalid UOM Code (CREATE)

{
  "status": "response",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_123456",
  "data": {
    "summary": {
      "total_documents": 1,
      "inserted": 0,
      "failed": 1
    },
    "failed_documents": ["SO-001"],
    "fail_details": {
      "invalid_uoms": [
        "Document 1 (Doc1No: SO-001), Item 1: UOM code 'INVALID' does not exist"
      ]
    }
  }
}

Invalid Currency Code (CREATE)

{
  "status": "response",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_123456",
  "data": {
    "summary": {
      "total_documents": 1,
      "inserted": 0,
      "failed": 1
    },
    "failed_documents": ["SO-001"],
    "fail_details": {
      "invalid_currencies": [
        "Document 1 (Doc1No: SO-001): Currency code 'INVALID' does not exist"
      ]
    }
  }
}

No Read Permission

{
  "status": "error",
  "timestamp": "2026-04-07T10:46:15+08:00",
  "request_id": "req_6612f3b9c21a7",
  "message": "Sales Order read permission denied"
}

No Create Permission

{
  "status": "error",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_123456",
  "message": "Sales Order create permission denied"
}

Common Errors — Sales Order Module

Error Message Cause Fix
"date_from and date_to are required" Missing date range (READ only) Add both fields to your request
"Invalid date format. Use YYYY-MM-DD format." Wrong date format Use YYYY-MM-DD — e.g. "2026-04-01"
"Date range cannot exceed 31 days." Date range too wide Narrow range to 31 days or fewer
"Invalid DocType 'XXX'. Allowed: SO" Wrong DocType in CREATE request Use "SO" as the DocType
"Missing fields - ItemCode, Description, Qty, FactorQty, UOM, HCUnitCost, HCLineAmt, BlankLine" Compulsory item fields not provided (CREATE) Include all required fields for each item
"UOM code 'X' does not exist" Invalid Unit of Measure (CREATE) Check the UOM exists in SKYBIZ (singular or plural form)
"Currency code 'X' does not exist" Invalid currency code (CREATE) Use a valid currency code (e.g., RM, SGD, USD)
"Customer Code 'X' does not exist" Invalid customer code Check the customer code exists in SKYBIZ
"HCLineAmt does not match Qty × HCUnitCost" Amount calculation mismatch Ensure HCLineAmt = Qty × HCUnitCost
"Header HCNetAmt does not match sum of HCLineAmt" Header total doesn’t match item totals Set HCNetAmt to the sum of all item HCLineAmt
"Document already exists" Duplicate Doc1No Use a unique Doc1No
"Sales Order read permission denied" No read permission for Sales Order module Enable read permission in portal by contacting your SkyBiz Admin

For complete field references and advanced usage, see the SKYBIZ API Advanced Documentation.