Customer Module

SKYBIZ API — Customer Module

Customer

The Customer module allows you to retrieve and create customer records in your SKYBIZ account. Supports both read and create operations.

Endpoint: /apiv2/modules/customer.php

Required Permissions: Customer — Read, Customer — Create


Read Customers

Retrieves customers modified within the given date range, ordered by CusCode.

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",
  "fields": [],
  "filters": {}
}

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
fields Array of specific fields to return. Empty [] returns all. No
filters Object to filter results (e.g., {"Town": "Kuala Lumpur"}) No

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)

Use the fields parameter to return only the fields you need. Leave empty to return all fields.

Field Type Description
CusCode string Unique customer code (identifier)
CusName string Customer name
Address string Full address
AreaCode string Area code
CurCode string Currency code (e.g., RM, SGD, USD)
Tel string Primary telephone
Tel2 string Secondary telephone
Fax string Fax number
Fax2 string Secondary fax number
Email string Email address
Contact string Contact person name
ContactTel string Contact person telephone
Town string Town/City
State string State
Country string Country
PostCode string Postal code
SalesPersonCode string Assigned salesperson code
CreditLimit float Credit limit amount
TermCode integer Payment term in days
StatusBadYN string Bad status flag — "0" or "1"
DateStart string Customer start date
DOB string Date of birth
Sex string Gender
MemberType string Member type
DateTimeModified string Last modified datetime — used as the date filter

Example 1 — Get All Customers (All Fields)

This request returns all customer fields for customers modified 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",
  "fields": [],
  "filters": {}
}

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 = "customer.php";

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

$requestParams = [
    "date_from" => $DATE_FROM,
    "date_to" => $DATE_TO,
    "fields" => [], // Leave empty for all fields
    "filters" => [] // Optional filters
];

// ============================================================
// 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": [
      {
        "CusCode": "CUST001",
        "CusName": "Acme Sdn Bhd",
        "CurCode": "RM",
        "Tel": "03-12345678",
        "Email": "billing@acme.com",
        "Town": "Petaling Jaya",
        "State": "Selangor",
        "DateTimeModified": "2026-04-15 10:30:00"
      },
      {
        "CusCode": "CUST002",
        "CusName": "Tech Solutions",
        "CurCode": "RM",
        "Tel": "03-87654321",
        "Email": "info@techsolutions.com",
        "Town": "Shah Alam",
        "State": "Selangor",
        "DateTimeModified": "2026-04-20 14:45:00"
      }
    ]
  }
}

Example 2 — Get Specific Fields Only

This request returns only CusCode, CusName, Email, and Tel fields.

Request

{
  "api_key": "your-api-key",
  "api_secret": "your-api-secret",
  "action": "read",
  "date_from": "2026-04-01",
  "date_to": "2026-04-30",
  "fields": ["CusCode", "CusName", "Email", "Tel"],
  "filters": {}
}

Example 3 — With Filters

This request returns only customers with TestAPI CusName.

Request

{
  "api_key": "your-api-key",
  "api_secret": "your-api-secret",
  "action": "read",
  "date_from": "2026-04-01",
  "date_to": "2026-04-30",
  "fields": [],
  "filters": {"CusName": "TestAPI"}
}

Postman Steps — READ Request

  1. Set method to POST

2. Enter URL: https://your-domain/01/clientportal/apiv2/modules/customer.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 Customer

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

Note: FinCatCode is automatically set to B55 by the system. Do not include it in your request.

Compulsory Fields

Field Type Description
AccountCode string GL account code
CusCode string Unique customer code. Must not already exist.
CusName string Customer name
CurCode string Currency code. Must exist in SKYBIZ currency table.
D_ay integer Payment term in days — e.g. 30
CategoryCode string Customer category

Optional Fields

Field Type Description
Address1 to Address4 string Address lines 1 to 4. Concatenated into Address field.
AreaCode string Area code
CreditLimit float Credit limit. Default: 0
SalesPersonCode string Assigned salesperson code
Tel / Tel2 string Phone numbers
Fax / Fax2 string Fax numbers
Contact / ContactTel string Contact person name and phone
URL / Email string Website URL and email address
Town / State / Country / PostCode string Address components
GSTNo string GST registration number
NRICNo string NRIC number
SalesTaxNo / TaxExemptionNo string Tax-related numbers
TaxTel / TaxEmail string Tax office contact details

Base Create Request Structure

{
  "api_key": "your-api-key",
  "api_secret": "your-api-secret",
  "action": "create",
  "customer_data": {
    "documents": [
      {
        "AccountCode": "AR-001",
        "CusCode": "CUST001",
        "CusName": "Customer Name",
        "CurCode": "RM",
        "D_ay": 30,
        "CategoryCode": "RETAIL",
        "Address1": "123 Jalan SS2",
        "Address2": "Section 2",
        "AreaCode": "SEL",
        "CreditLimit": 10000.00,
        "SalesPersonCode": "SALES01",
        "Tel": "03-12345678",
        "Email": "customer@test.com",
        "Town": "Petaling Jaya",
        "State": "Selangor",
        "Country": "Malaysia",
        "PostCode": "47300"
      }
    ]
  }
}

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 = "customer.php";

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

$DATA_KEY = "customer_data";

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

$DOCUMENTS = [];

// --- Customer example ---
$DOCUMENTS[] = [
    "AccountCode" => "AR-001",
    "CusCode" => "CUST001",
    "CusName" => "Customer Name",
    "CurCode" => "RM",
    "D_ay" => 30,
    "CategoryCode" => "RETAIL",
    "Address1" => "123 Jalan SS2",
    "Address2" => "Section 2",
    "AreaCode" => "SEL",
    "CreditLimit" => 10000.00,
    "SalesPersonCode" => "SALES01",
    "Tel" => "03-12345678",
    "Email" => "customer@test.com",
    "Town" => "Petaling Jaya",
    "State" => "Selangor",
    "Country" => "Malaysia",
    "PostCode" => "47300"
];

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

$totalDocuments = 0;

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

    if (empty($document['CusCode'])) {
        echo json_encode([
            "status" => "REJECTED_BY_CLIENT",
            "timestamp" => date("c"),
            "request_id" => uniqid("req_"),
            "message" => "CLIENT-SIDE REJECTION: Document at position {$totalDocuments} has empty CusCode",
            "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": ["CUST001"],
    "failed_documents": [],
    "fail_details": {
      "compulsory_fields_missing": [],
      "duplicate_customers": [],
      "invalid_currencies": [],
      "validation_errors": []
    }
  }
}

Response (Error — Duplicate Customer)

{
  "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": ["CUST001"],
    "fail_details": {
      "duplicate_customers": [
        {
          "cuscode": "CUST001",
          "error": "Customer code already exists"
        }
      ]
    }
  }
}

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 Date Format

{
  "status": "error",
  "timestamp": "2026-04-07T10:46:15+08:00",
  "request_id": "req_6612f3b9c21a7",
  "message": "Invalid date format. Use YYYY-MM-DD format."
}

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": ["CUST001"],
    "fail_details": {
      "compulsory_fields_missing": [
        "Document 1 (CusCode: CUST001): Missing fields - AccountCode, CusName, CurCode, D_ay, CategoryCode"
      ]
    }
  }
}

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": ["CUST001"],
    "fail_details": {
      "invalid_currencies": [
        "Document 1 (CusCode: CUST001): Currency code 'INVALID' does not exist"
      ]
    }
  }
}

No Read Permission

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

No Create Permission

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

Common Errors — Customer 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
"Missing fields - AccountCode, CusName, CurCode, D_ay, CategoryCode" Compulsory fields not provided (CREATE) Include all required fields for Customer module
"Currency code 'X' does not exist" Invalid currency code (CREATE) Use a valid currency code (e.g., RM, SGD, USD)
"Customer code already exists" Duplicate CusCode in database (CREATE) Use a unique customer code or update existing record if permitted
"Duplicate CusCode found in the same batch" Same CusCode appears multiple times in one request (CREATE) Remove duplicate entries from your documents array
"Customer read permission denied" No read permission for Customer module Enable read permission in portal by contacting your SkyBiz Admin