Fr8Labs Simplified API — Partner Integration Guide


Overview

The Fr8Labs Simplified API provides a secure, lightweight way for logistics partners to integrate with Fr8Labs freight management system.

This API currently enables you to:

  • Retrieve cargo manifest and shipment data

  • Update HBL-level milestone information (cargo received, cargo released, etc.)

  • Create container-level memos with photos and tally sheets

No complex authentication flows or GraphQL knowledge required — just simple REST endpoints with API key authentication.


Getting Started

Step 1 — Request API Access

Contact your Fr8Labs account manager to request API access. You will receive:

  • API Key — Your unique authentication token

  • Developer Sandbox Access — Test environment for development

Step 2 — Test in Sandbox

Before going live, test your integration in our developer sandbox environment. This allows you to:

  • Validate your API calls

  • Test with sample data

  • Debug without affecting production

Sandbox URL: Provided upon request Production URL: https://notification-hub.fr8labs.co

Step 3 — Go Live

Once testing is complete, use your production API key with the production URL.


Authentication

All API requests require a Bearer token in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Example:

curl -H "Authorization: Bearer edi_abc123..." \
     "https://notification-hub.fr8labs.co/api/edi/manifest?job_reference=SE-2512-022"

API Endpoints

Health Check

GET /api/edi/health

Check if the API is operational. No authentication required.

Response:

{
  "service": "Fr8Labs EDI Cargo Manifest API",
  "version": "1.0.0",
  "status": "operational",
  "timestamp": "2025-12-15T10:00:00.000Z"
}

Get Cargo Manifest

GET /api/edi/manifest

Retrieve cargo manifest data for a shipment.

Query Parameters:

Parameter

Required

Description

job_reference

Yes

Shipment number or job reference (e.g., SE-2512-022 or OESHA25110014)

master_only

No

Yes to return master-level summary only. Default: No

Example Request:

curl -X GET \
  "https://notification-hub.fr8labs.co/api/edi/manifest?job_reference=SE-2512-022" \
  -H "Authorization: Bearer YOUR_API_KEY"

Success Response (200):

{
  "success": true,
  "query": {
    "jobReference": "SE-2512-022",
    "masterOnly": "No",
    "cardId": 1455
  },
  "metadata": {
    "totalRecords": 3,
    "masterCount": 1,
    "houseCount": 2,
    "executionTimeMs": 245,
    "columnCount": 25
  },
  "columns": ["ShipmentNo", "HBLNo", "Consignee", "..."],
  "data": [
    {
      "ShipmentNo": "SE-2512-022",
      "HBLNo": "SE-2512-0220001",
      "Consignee": "ABC Trading Pte Ltd",
      "..."
    }
  ]
}

Error Response (404):

{
  "success": false,
  "error": "No manifest data found for job reference: SE-2512-999",
  "code": "NOT_FOUND"
}

Update HBL Milestone

POST /api/edi/hbl-update

Update milestone fields on an HBL (House Bill of Lading).

Supported Fields:

Field

Type

Description

cargoReleasedDate

DateTime (ISO 8601)

Date/time cargo was released

cargoReceivedDate

DateTime (ISO 8601)

Date/time cargo was received at facility

unstuffingReleaseDate

DateTime (ISO 8601)

Date/time of unstuffing/stuffing release

isStorageChargesIncurred

Boolean

Whether storage charges apply

storageChargesAmount

Number

Storage/rent amount — creates a note in the system


Export Shipment Example

For export shipments (e.g., stuffing operations at CFS), typical fields are:

  • cargoReceivedDate — When cargo arrived at the facility

  • unstuffingReleaseDate — Stuffing completion date (reusing this field for stuffing)

Request:

curl -X POST \
  "https://notification-hub.fr8labs.co/api/edi/hbl-update" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "hblReference": "SE-2512-0210002",
    "updates": {
      "cargoReceivedDate": "2025-12-14T09:00:00.000Z",
      "unstuffingReleaseDate": "2025-12-15T14:30:00.000Z"
    }
  }'

Success Response (200):

{
  "success": true,
  "message": "HBL updated successfully",
  "hblReference": "SE-2512-0210002",
  "shipmentNo": "SE-2512-021",
  "shipmentHBLId": 236881,
  "updatedFields": {
    "hbl": [],
    "hblDetail": ["cargoReceivedDate", "unstuffingReleaseDate"],
    "memo": []
  }
}

Import Shipment Example

For import shipments (e.g., unstuffing operations at CFS), typical fields are:

  • unstuffingReleaseDate — Unstuffing completion date

  • cargoReleasedDate — When container was released

  • isStorageChargesIncurred — Flag for storage charges

  • storageChargesAmount — Actual storage amount (creates a note)

Request:

curl -X POST \
  "https://notification-hub.fr8labs.co/api/edi/hbl-update" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "hblReference": "SI-2512-0110002",
    "updates": {
      "unstuffingReleaseDate": "2025-12-15T10:00:00.000Z",
      "cargoReleasedDate": "2025-12-14T08:30:00.000Z",
      "isStorageChargesIncurred": true,
      "storageChargesAmount": 250.00
    }
  }'

Success Response (200):

{
  "success": true,
  "message": "HBL updated successfully",
  "hblReference": "SI-2512-0110002",
  "shipmentNo": "SI-2512-011",
  "shipmentHBLId": 238442,
  "updatedFields": {
    "hbl": [],
    "hblDetail": ["unstuffingReleaseDate", "cargoReceivedDate", "isStorageChargesIncurred"],
    "memo": ["storageChargesAmount"]
  },
  "memoCreated": true
}

Error Responses:

HTTP Code

Error Code

Description

400

PARAM_MISSING

Missing hblReference or updates in request body

400

FIELD_NOT_ALLOWED

Attempting to update a field not in the allowed list

404

HBL_NOT_FOUND

HBL reference not found

401

AUTH_MISSING

Missing Authorization header

403

AUTH_INVALID_KEY

Invalid or revoked API key

503

CLIENT_NOT_CONFIGURED

API key not fully configured (contact Fr8Labs)


Create Container Memos

POST /api/edi/container-memo

Create memos at the shipment (MBL) level for each container, typically used to attach tally sheets and photos from stuffing or unstuffing operations.

Request Body (JSON):

{
  "jobReference": "SE-2512-021",
  "containers": [
    {
      "containerNo": "MSCU1234567",
      "tallySheetUrl": "https://example.com/tally1.pdf",
      "photoUrl": "https://example.com/photo1.jpg"
    }
  ]
}

Parameters:

Field

Required

Description

jobReference

Yes

Master job number (without HBL suffix)

containers

Yes

Array of container objects

containers[].containerNo

Yes

Container number

containers[].tallySheetUrl

No*

URL to tally sheet document

containers[].photoUrl

No*

URL to photo

*At least one of tallySheetUrl or photoUrl is required per container.


Export Stuffing Example

For export shipments, this is typically used to attach stuffing photos and tally sheets:

Request:

curl -X POST \
  "https://notification-hub.fr8labs.co/api/edi/container-memo" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jobReference": "SE-2512-021",
    "containers": [
      {
        "containerNo": "MSCU1234567",
        "tallySheetUrl": "https://storage.example.com/tally/SE2512021-MSCU1234567.pdf",
        "photoUrl": "https://storage.example.com/photos/SE2512021-MSCU1234567-stuffing.jpg"
      },
      {
        "containerNo": "TCLU7654321",
        "tallySheetUrl": "https://storage.example.com/tally/SE2512021-TCLU7654321.pdf",
        "photoUrl": "https://storage.example.com/photos/SE2512021-TCLU7654321-stuffing.jpg"
      }
    ]
  }'

Success Response (200):

{
  "success": true,
  "message": "Created 2 container memo(s)",
  "jobReference": "SE-2512-021",
  "shipmentId": 212956,
  "containers": [
    {
      "containerNo": "MSCU1234567",
      "success": true,
      "memoId": 45123
    },
    {
      "containerNo": "TCLU7654321",
      "success": true,
      "memoId": 45124
    }
  ]
}

Each container creates a memo in the system like:

Container: MSCU1234567
Tally Sheet: https://storage.example.com/tally/SE2512021-MSCU1234567.pdf
Photo: https://storage.example.com/photos/SE2512021-MSCU1234567-stuffing.jpg

Error Responses:

HTTP Code

Error Code

Description

400

PARAM_MISSING

Missing jobReference, containers, or required container fields

404

NOT_FOUND

Shipment not found

401

AUTH_MISSING

Missing Authorization header

403

AUTH_INVALID_KEY

Invalid or revoked API key


Integration Examples

n8n Workflow — HBL Update

HTTP Request Node Configuration:

Setting

Value

Method

POST

URL

https://notification-hub.fr8labs.co/api/edi/hbl-update

Authentication

None (use header)

Send Headers

Yes

Header Name

Authorization

Header Value

Bearer YOUR_API_KEY

Send Body

Yes

Body Content Type

JSON

Body:

{
  "hblReference": "{{ $json.hbl_number }}",
  "updates": {
    "cargoReceivedDate": "{{ $json.received_date }}",
    "unstuffingReleaseDate": "{{ $json.unstuffing_date }}",
    "isStorageChargesIncurred": {{ $json.has_storage }},
    "storageChargesAmount": {{ $json.storage_amount }}
  }
}

n8n Workflow — Container Memo

HTTP Request Node Configuration:

Setting

Value

Method

POST

URL

https://notification-hub.fr8labs.co/api/edi/container-memo

Authentication

None (use header)

Send Headers

Yes

Header Name

Authorization

Header Value

Bearer YOUR_API_KEY

Send Body

Yes

Body Content Type

JSON

Body:

{
  "jobReference": "{{ $json.job_number }}",
  "containers": [
    {
      "containerNo": "{{ $json.container_no }}",
      "tallySheetUrl": "{{ $json.tally_url }}",
      "photoUrl": "{{ $json.photo_url }}"
    }
  ]
}

Python Example

import requests

API_KEY = "edi_your_api_key_here"
BASE_URL = "https://notification-hub.fr8labs.co"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
}

# Get manifest
response = requests.get(
    f"{BASE_URL}/api/edi/manifest",
    params={"job_reference": "SE-2512-021"},
    headers=headers
)
print(response.json())

# Update HBL (Export - stuffing)
response = requests.post(
    f"{BASE_URL}/api/edi/hbl-update",
    headers=headers,
    json={
        "hblReference": "SE-2512-0210002",
        "updates": {
            "cargoReceivedDate": "2025-12-14T09:00:00.000Z",
            "unstuffingReleaseDate": "2025-12-15T14:30:00.000Z"
        }
    }
)
print(response.json())

# Update HBL (Import - unstuffing with storage)
response = requests.post(
    f"{BASE_URL}/api/edi/hbl-update",
    headers=headers,
    json={
        "hblReference": "SI-2512-0110002",
        "updates": {
            "unstuffingReleaseDate": "2025-12-15T10:00:00.000Z",
            "cargoReceivedDate": "2025-12-14T08:30:00.000Z",
            "isStorageChargesIncurred": True,
            "storageChargesAmount": 250.00
        }
    }
)
print(response.json())

# Create container memos (Export - stuffing photos)
response = requests.post(
    f"{BASE_URL}/api/edi/container-memo",
    headers=headers,
    json={
        "jobReference": "SE-2512-021",
        "containers": [
            {
                "containerNo": "MSCU1234567",
                "tallySheetUrl": "https://example.com/tally1.pdf",
                "photoUrl": "https://example.com/photo1.jpg"
            }
        ]
    }
)
print(response.json())

JavaScript/Node.js Example

const API_KEY = 'edi_your_api_key_here';
const BASE_URL = 'https://notification-hub.fr8labs.co';

const headers = {
  'Authorization': `Bearer ${API_KEY}`,
  'Content-Type': 'application/json'
};

// Get manifest
const manifestResponse = await fetch(
  `${BASE_URL}/api/edi/manifest?job_reference=SE-2512-021`,
  { headers }
);
console.log(await manifestResponse.json());

// Update HBL (Export - stuffing)
const exportUpdate = await fetch(
  `${BASE_URL}/api/edi/hbl-update`,
  {
    method: 'POST',
    headers,
    body: JSON.stringify({
      hblReference: 'SE-2512-0210002',
      updates: {
        cargoReceivedDate: '2025-12-14T09:00:00.000Z',
        unstuffingReleaseDate: '2025-12-15T14:30:00.000Z'
      }
    })
  }
);
console.log(await exportUpdate.json());

// Update HBL (Import - unstuffing with storage)
const importUpdate = await fetch(
  `${BASE_URL}/api/edi/hbl-update`,
  {
    method: 'POST',
    headers,
    body: JSON.stringify({
      hblReference: 'SI-2512-0110002',
      updates: {
        unstuffingReleaseDate: '2025-12-15T10:00:00.000Z',
        cargoReceivedDate: '2025-12-14T08:30:00.000Z',
        isStorageChargesIncurred: true,
        storageChargesAmount: 250.00
      }
    })
  }
);
console.log(await importUpdate.json());

// Create container memos (Export - stuffing photos)
const memoResponse = await fetch(
  `${BASE_URL}/api/edi/container-memo`,
  {
    method: 'POST',
    headers,
    body: JSON.stringify({
      jobReference: 'SE-2512-021',
      containers: [
        {
          containerNo: 'MSCU1234567',
          tallySheetUrl: 'https://example.com/tally1.pdf',
          photoUrl: 'https://example.com/photo1.jpg'
        }
      ]
    })
  }
);
console.log(await memoResponse.json());

Date/Time Format

All date/time fields use ISO 8601 format:

YYYY-MM-DDTHH:mm:ss.sssZ

Examples:

Description

Value

December 15, 2025, midnight UTC

2025-12-15T00:00:00.000Z

December 15, 2025, 2:30 PM UTC

2025-12-15T14:30:00.000Z

December 15, 2025, 10:30 AM Singapore (UTC+8)

2025-12-15T02:30:00.000Z

Note: All times should be in UTC. If your system uses local time, convert to UTC before sending.


Rate Limits

Limit

Value

Requests per minute

60

Requests per hour

1000

If you exceed rate limits, you'll receive a 429 Too Many Requests response. Wait before retrying.


Best Practices

  1. Store your API key securely — Never commit API keys to source control or expose them client-side.

  2. Handle errors gracefully — Check response codes and implement retry logic for transient failures.

  3. Use the sandbox first — Test thoroughly before going live.

  4. Log API responses — Keep logs for debugging and reconciliation.

  5. Validate data before sending — Ensure dates are valid ISO 8601 format and field values are correct types.


Support

For technical support or to request API access:


Changelog

Version

Date

Changes

1.1.0

Dec 2025

Added unstuffingReleaseDate field, new container-memo endpoint

1.0.0

Dec 2025

Initial release with manifest GET and HBL update POST