Outsider API Complete Documentation
Overview
The Outsider API provides external partners with comprehensive shipment management capabilities. This documentation covers all endpoints, scenarios, success responses, and error conditions.
Base URL: https://track.oklabs.my.id
Authentication: Token-based authentication required
Content-Type: application/json
Table of Contents
- Authentication
- Purchase Order Management
- PO Line Management
- Shipment Management
- Provider Scenarios
- AJU Management
- Error Handling
- Complete Examples
Authentication
Header Format
Authorization: Token 1dce52a4f1a07fdebf8daa34733480063deb8047
Content-Type: application/json
Authentication Errors
❌ No Token Provided
Request:
GET /shipment/outsider/
Response: 401 Unauthorized
{
"detail": "Authentication credentials were not provided."
}
❌ Invalid Token
Request:
GET /shipment/outsider/
Authorization: Token invalid_token_123
Response: 401 Unauthorized
{
"detail": "Invalid token."
}
❌ Wrong Token Format
Request:
GET /shipment/outsider/
Authorization: Bearer 1dce52a4f1a07fdebf8daa34733480063deb8047
Response: 401 Unauthorized
{
"detail": "Authentication credentials were not provided."
}
Purchase Order Management
Create Purchase Order
Endpoint: POST /shipment/po/
✅ Success Case
Request:
{
"po_number": "PO-EXTERNAL-2025-001"
}
Response: 201 Created
{
"id": 8,
"po_number": "PO-EXTERNAL-2025-001",
"created_at": "2025-08-09T11:32:12.033377Z",
"lines": []
}
❌ Missing Required Field
Request:
{}
Response: 400 Bad Request
{
"po_number": [
"This field is required."
]
}
✅ Duplicate PO Numbers Allowed
Note: The system allows duplicate PO numbers but creates separate records.
Request:
{
"po_number": "PO-EXTERNAL-2025-001"
}
Response: 201 Created
{
"id": 9,
"po_number": "PO-EXTERNAL-2025-001",
"created_at": "2025-08-09T11:32:13.751286Z",
"lines": []
}
PO Line Management
Create PO Line
Endpoint: POST /shipment/po-line/
✅ Success Case
Request:
{
"po": 8,
"line_code": "LINE-ELECTRONICS-001",
"total_qty": 1000
}
Response: 201 Created
{
"id": 10,
"po": 8,
"line_code": "LINE-ELECTRONICS-001",
"total_qty": 1000,
"shipments": []
}
❌ Non-existent PO ID
Request:
{
"po": 99999,
"line_code": "TEST-LINE",
"total_qty": 100
}
Response: 400 Bad Request
{
"po": [
"Invalid pk \"99999\" - object does not exist."
]
}
❌ Invalid Quantity (Negative)
Request:
{
"po": 8,
"line_code": "TEST-INVALID-QTY",
"total_qty": -50
}
Response: 400 Bad Request
{
"total_qty": [
"Ensure this value is greater than or equal to 0."
]
}
✅ Duplicate Line Codes Allowed
Note: The system allows duplicate line codes within the same PO.
Shipment Management
Create Shipment
Endpoint: POST /shipment/outsider/
✅ Success Case - Full Shipment
Request:
{
"po_number": "PO-EXTERNAL-2025-001",
"line_code": "LINE-ELECTRONICS-001",
"shipped_qty": 1000,
"outsider_reference": "EXT-REF-FULL-001"
}
Response: 201 Created
{
"id": 10,
"po_number": "PO-EXTERNAL-2025-001",
"line_code": "LINE-ELECTRONICS-001",
"total_qty": 1000,
"shipped_qty": 1000,
"first_mile_awb": null,
"last_mile_awb": null,
"ceisa_aju": null,
"first_mile_status": null,
"customs_status": "pending",
"last_mile_status": null,
"process_start": null,
"gate_out": null,
"payment_due": null,
"first_mile_provider_name": null,
"last_mile_provider_name": null,
"outsider_reference": "EXT-REF-FULL-001",
"is_partial_shipment": false,
"created_at": "2025-08-09T11:35:00.123456Z",
"updated_at": "2025-08-09T11:35:00.123456Z"
}
✅ Success Case - Partial Shipment
Request:
{
"po_number": "PO-EXTERNAL-2025-001",
"line_code": "LINE-ELECTRONICS-001",
"shipped_qty": 500,
"outsider_reference": "EXT-REF-PARTIAL-001"
}
Response: 201 Created
{
"id": 11,
"po_number": "PO-EXTERNAL-2025-001",
"line_code": "LINE-ELECTRONICS-001",
"total_qty": 1000,
"shipped_qty": 500,
"first_mile_awb": null,
"last_mile_awb": null,
"ceisa_aju": null,
"first_mile_status": null,
"customs_status": "pending",
"last_mile_status": null,
"process_start": null,
"gate_out": null,
"payment_due": null,
"first_mile_provider_name": null,
"last_mile_provider_name": null,
"outsider_reference": "EXT-REF-PARTIAL-001",
"is_partial_shipment": true,
"created_at": "2025-08-09T11:35:30.123456Z",
"updated_at": "2025-08-09T11:35:30.123456Z"
}
❌ Non-existent PO Number
Request:
{
"po_number": "PO-NONEXISTENT-123",
"line_code": "LINE-TEST",
"shipped_qty": 50
}
Response: 400 Bad Request
{
"non_field_errors": [
"Purchase Order PO-NONEXISTENT-123 not found"
]
}
❌ Missing Required Fields
Request:
{
"po_number": "PO-EXTERNAL-2025-001"
}
Response: 400 Bad Request
{
"line_code": [
"This field is required."
],
"shipped_qty": [
"This field is required."
]
}
Update Shipment
Endpoint: PATCH /shipment/outsider/{shipment_id}/
✅ Success Case - Quantity Update
Request:
{
"shipped_qty": 750
}
Response: 200 OK
{
"id": 11,
"po_number": "PO-EXTERNAL-2025-001",
"line_code": "LINE-ELECTRONICS-001",
"total_qty": 1000,
"shipped_qty": 750,
"first_mile_awb": null,
"last_mile_awb": null,
"ceisa_aju": null,
"first_mile_status": null,
"customs_status": "pending",
"last_mile_status": null,
"process_start": null,
"gate_out": null,
"payment_due": null,
"first_mile_provider_name": null,
"last_mile_provider_name": null,
"outsider_reference": "EXT-REF-PARTIAL-001",
"is_partial_shipment": true,
"created_at": "2025-08-09T11:35:30.123456Z",
"updated_at": "2025-08-09T11:36:00.123456Z"
}
❌ Quantity Exceeds Remaining
Request:
{
"shipped_qty": 99999
}
Response: 400 Bad Request
{
"error": "Quantity exceeds remaining: 500"
}
List Shipments
Endpoint: GET /shipment/outsider/
✅ Success Case
Response: 200 OK
[
{
"id": 11,
"po_number": "PO-EXTERNAL-2025-001",
"line_code": "LINE-ELECTRONICS-001",
"total_qty": 1000,
"shipped_qty": 750,
"first_mile_awb": null,
"last_mile_awb": null,
"ceisa_aju": null,
"first_mile_status": null,
"customs_status": "pending",
"last_mile_status": null,
"process_start": null,
"gate_out": null,
"payment_due": null,
"first_mile_provider_name": null,
"last_mile_provider_name": null,
"outsider_reference": "EXT-REF-PARTIAL-001",
"is_partial_shipment": true,
"created_at": "2025-08-09T11:35:30.123456Z",
"updated_at": "2025-08-09T11:36:00.123456Z"
}
]
Get Specific Shipment
Endpoint: GET /shipment/outsider/{shipment_id}/
✅ Success Case
Response: 200 OK
{
"id": 11,
"po_number": "PO-EXTERNAL-2025-001",
"line_code": "LINE-ELECTRONICS-001",
"total_qty": 1000,
"shipped_qty": 750,
"first_mile_awb": null,
"last_mile_awb": null,
"ceisa_aju": null,
"first_mile_status": null,
"customs_status": "pending",
"last_mile_status": null,
"process_start": null,
"gate_out": null,
"payment_due": null,
"first_mile_provider_name": null,
"last_mile_provider_name": null,
"outsider_reference": "EXT-REF-PARTIAL-001",
"is_partial_shipment": true,
"created_at": "2025-08-09T11:35:30.123456Z",
"updated_at": "2025-08-09T11:36:00.123456Z"
}
❌ Non-existent Shipment ID
Response: 404 Not Found
{
"detail": "No POLineShipment matches the given query."
}
Provider Scenarios
Scenario 1: Single Provider (Same Provider for Both Miles)
Step 1: Add First Mile Provider
Request: PATCH /shipment/outsider/{shipment_id}/
{
"first_mile_provider_id": 2,
"first_mile_awb": "5451596323",
"use_same_provider": true
}
Response: 200 OK
{
"id": 11,
"po_number": "PO-EXTERNAL-2025-001",
"line_code": "LINE-ELECTRONICS-001",
"total_qty": 1000,
"shipped_qty": 750,
"first_mile_awb": "5451596323",
"last_mile_awb": "5451596323",
"ceisa_aju": null,
"first_mile_status": null,
"customs_status": "pending",
"last_mile_status": null,
"process_start": null,
"gate_out": null,
"payment_due": null,
"first_mile_provider_name": "DHL Express",
"last_mile_provider_name": "DHL Express",
"outsider_reference": "EXT-REF-PARTIAL-001",
"is_partial_shipment": true,
"created_at": "2025-08-09T11:35:30.123456Z",
"updated_at": "2025-08-09T11:37:00.123456Z"
}
Scenario 2: Multi-Provider (Different Providers)
Step 1: Add First Mile Provider
Request: PATCH /shipment/outsider/{shipment_id}/
{
"first_mile_provider_id": 2,
"first_mile_awb": "5451596323"
}
Response: 200 OK
{
"id": 12,
"po_number": "PO-EXTERNAL-2025-001",
"line_code": "LINE-ELECTRONICS-002",
"total_qty": 500,
"shipped_qty": 200,
"first_mile_awb": "5451596323",
"last_mile_awb": null,
"ceisa_aju": null,
"first_mile_status": null,
"customs_status": "pending",
"last_mile_status": null,
"process_start": null,
"gate_out": null,
"payment_due": null,
"first_mile_provider_name": "DHL Express",
"last_mile_provider_name": null,
"outsider_reference": null,
"is_partial_shipment": true,
"created_at": "2025-08-09T11:38:00.123456Z",
"updated_at": "2025-08-09T11:38:30.123456Z"
}
Step 2: Add Last Mile Provider
Request: PATCH /shipment/outsider/{shipment_id}/
{
"last_mile_provider_id": 3,
"last_mile_awb": "883134258320"
}
Response: 200 OK
{
"id": 12,
"po_number": "PO-EXTERNAL-2025-001",
"line_code": "LINE-ELECTRONICS-002",
"total_qty": 500,
"shipped_qty": 200,
"first_mile_awb": "5451596323",
"last_mile_awb": "883134258320",
"ceisa_aju": null,
"first_mile_status": null,
"customs_status": "pending",
"last_mile_status": null,
"process_start": null,
"gate_out": null,
"payment_due": null,
"first_mile_provider_name": "DHL Express",
"last_mile_provider_name": "FEDEX",
"outsider_reference": null,
"is_partial_shipment": true,
"created_at": "2025-08-09T11:38:00.123456Z",
"updated_at": "2025-08-09T11:39:00.123456Z"
}
Scenario 3: Single Forwarder (Same Provider, Same AWB)
Request: PATCH /shipment/outsider/{shipment_id}/
{
"first_mile_provider_id": 3,
"first_mile_awb": "883134258320",
"use_single_forwarder": true
}
Response: 200 OK
{
"id": 13,
"po_number": "PO-EXTERNAL-2025-001",
"line_code": "LINE-ELECTRONICS-003",
"total_qty": 300,
"shipped_qty": 150,
"first_mile_awb": "883134258320",
"last_mile_awb": "883134258320",
"ceisa_aju": null,
"first_mile_status": null,
"customs_status": "pending",
"last_mile_status": null,
"process_start": null,
"gate_out": null,
"payment_due": null,
"first_mile_provider_name": "FEDEX",
"last_mile_provider_name": "FEDEX",
"outsider_reference": null,
"is_partial_shipment": true,
"created_at": "2025-08-09T11:40:00.123456Z",
"updated_at": "2025-08-09T11:40:30.123456Z"
}
Provider Error Scenarios
❌ Invalid Provider ID
Request:
{
"first_mile_provider_id": 99999
}
Response: 400 Bad Request
{
"non_field_errors": [
"First mile provider not found"
]
}
AJU Management
Add AJU Number
Request: PATCH /shipment/outsider/{shipment_id}/
{
"ceisa_aju": "05010000622320250808001234"
}
Response: 200 OK
{
"id": 12,
"po_number": "PO-EXTERNAL-2025-001",
"line_code": "LINE-ELECTRONICS-002",
"total_qty": 500,
"shipped_qty": 200,
"first_mile_awb": "5451596323",
"last_mile_awb": "883134258320",
"ceisa_aju": "05010000622320250808001234",
"first_mile_status": null,
"customs_status": "in_process",
"last_mile_status": null,
"process_start": null,
"gate_out": null,
"payment_due": null,
"first_mile_provider_name": "DHL Express",
"last_mile_provider_name": "FEDEX",
"outsider_reference": null,
"is_partial_shipment": true,
"created_at": "2025-08-09T11:38:00.123456Z",
"updated_at": "2025-08-09T11:41:00.123456Z"
}
Update AJU Number
Request: PATCH /shipment/outsider/{shipment_id}/
{
"ceisa_aju": "05010000622320250808005678"
}
Response: 200 OK
{
"id": 12,
"po_number": "PO-EXTERNAL-2025-001",
"line_code": "LINE-ELECTRONICS-002",
"total_qty": 500,
"shipped_qty": 200,
"first_mile_awb": "5451596323",
"last_mile_awb": "883134258320",
"ceisa_aju": "05010000622320250808005678",
"first_mile_status": null,
"customs_status": "in_process",
"last_mile_status": null,
"process_start": null,
"gate_out": null,
"payment_due": null,
"first_mile_provider_name": "DHL Express",
"last_mile_provider_name": "FEDEX",
"outsider_reference": null,
"is_partial_shipment": true,
"created_at": "2025-08-09T11:38:00.123456Z",
"updated_at": "2025-08-09T11:42:00.123456Z"
}
AJU Exclusion Rules
❌ Excluded AJU Number
Request:
{
"ceisa_aju": "000020001234567890123456"
}
Response: 400 Bad Request
{
"non_field_errors": [
"AJU 000020001234567890123456 starts with '00002' and will be excluded from CEISA tracking"
]
}
✅ Invalid AJU Format Accepted
Note: The system accepts AJU numbers with invalid formats but may not track them properly.
Request:
{
"ceisa_aju": "INVALID-AJU-123"
}
Response: 200 OK
{
"id": 13,
"po_number": "PO-EXTERNAL-2025-001",
"line_code": "LINE-ELECTRONICS-003",
"total_qty": 300,
"shipped_qty": 150,
"first_mile_awb": "883134258320",
"last_mile_awb": "883134258320",
"ceisa_aju": "INVALID-AJU-123",
"first_mile_status": null,
"customs_status": "in_process",
"last_mile_status": null,
"process_start": null,
"gate_out": null,
"payment_due": null,
"first_mile_provider_name": "FEDEX",
"last_mile_provider_name": "FEDEX",
"outsider_reference": null,
"is_partial_shipment": true,
"created_at": "2025-08-09T11:40:00.123456Z",
"updated_at": "2025-08-09T11:43:00.123456Z"
}
Error Handling
Common Error Response Formats
Validation Errors (400 Bad Request)
{
"field_name": [
"Error message for field"
],
"non_field_errors": [
"General error message"
]
}
Authentication Errors (401 Unauthorized)
{
"detail": "Authentication credentials were not provided."
}
Not Found Errors (404 Not Found)
{
"detail": "No POLineShipment matches the given query."
}
Server Errors (500 Internal Server Error)
<!doctype html>
<html lang="en">
<head>
<title>Server Error (500)</title>
</head>
<body>
<h1>Server Error (500)</h1><p></p>
</body>
</html>
Error Scenarios Summary
| Scenario | Status Code | Response Format |
|---|---|---|
| Missing authentication | 401 | {"detail": "Authentication credentials were not provided."} |
| Invalid token | 401 | {"detail": "Invalid token."} |
| Missing required fields | 400 | {"field_name": ["This field is required."]} |
| Invalid foreign key | 400 | {"field": ["Invalid pk \"99999\" - object does not exist."]} |
| Business logic violation | 400 | {"non_field_errors": ["Descriptive error message"]} |
| Resource not found | 404 | {"detail": "No [Model] matches the given query."} |
| Server error | 500 | HTML error page |
Complete Examples
Complete Workflow Example
1. Create Purchase Order
curl -X POST "https://track.oklabs.my.id/shipment/po/" \
-H "Authorization: Token 1dce52a4f1a07fdebf8daa34733480063deb8047" \
-H "Content-Type: application/json" \
-d '{"po_number": "PO-EXAMPLE-2025-001"}'
2. Create PO Lines
curl -X POST "https://track.oklabs.my.id/shipment/po-line/" \
-H "Authorization: Token 1dce52a4f1a07fdebf8daa34733480063deb8047" \
-H "Content-Type: application/json" \
-d '{"po": 1, "line_code": "LINE-EXAMPLE-001", "total_qty": 1000}'
3. Create Shipment
curl -X POST "https://track.oklabs.my.id/shipment/outsider/" \
-H "Authorization: Token 1dce52a4f1a07fdebf8daa34733480063deb8047" \
-H "Content-Type: application/json" \
-d '{
"po_number": "PO-EXAMPLE-2025-001",
"line_code": "LINE-EXAMPLE-001",
"shipped_qty": 500,
"outsider_reference": "EXT-REF-001"
}'
4. Add Provider Information
curl -X PATCH "https://track.oklabs.my.id/shipment/outsider/1/" \
-H "Authorization: Token 1dce52a4f1a07fdebf8daa34733480063deb8047" \
-H "Content-Type: application/json" \
-d '{
"first_mile_provider_id": 2,
"first_mile_awb": "5451596323",
"use_same_provider": true
}'
5. Add AJU Number
curl -X PATCH "https://track.oklabs.my.id/shipment/outsider/1/" \
-H "Authorization: Token 1dce52a4f1a07fdebf8daa34733480063deb8047" \
-H "Content-Type: application/json" \
-d '{"ceisa_aju": "05010000622320250808001234"}'
6. Track Shipment
curl -X GET "https://track.oklabs.my.id/shipment/outsider/1/" \
-H "Authorization: Token 1dce52a4f1a07fdebf8daa34733480063deb8047"
Provider IDs Reference
| Provider | ID | Name |
|---|---|---|
| DHL Express | 2 | DHL Express |
| FedEx | 3 | FEDEX |
Field Descriptions
| Field | Type | Required | Description |
|---|---|---|---|
po_number |
string | Yes | Purchase Order identifier |
line_code |
string | Yes | PO Line identifier |
shipped_qty |
integer | Yes | Quantity being shipped |
first_mile_provider_id |
integer | No | Provider ID for first mile delivery |
first_mile_awb |
string | No | AWB/tracking number for first mile |
last_mile_provider_id |
integer | No | Provider ID for last mile delivery |
last_mile_awb |
string | No | AWB/tracking number for last mile |
ceisa_aju |
string | No | CEISA AJU number for customs |
outsider_reference |
string | No | External reference number |
use_same_provider |
boolean | No | Auto-set last mile to same as first mile |
use_single_forwarder |
boolean | No | Use same provider and AWB for both miles |
Status Values
Customs Status
pending- Initial statusin_process- AJU submitted to CEISAcleared- Customs clearance completedheld- Held by customsrejected- Customs rejected
Provider Status
null- No tracking data available- Status values depend on provider API responses
Support
For technical support or API issues:
- Documentation: This document
- Test Environment:
https://track.oklabs.my.id - Swagger UI:
https://track.oklabs.my.id/swagger/
Note: This API is designed for external partner integration. All endpoints require valid authentication tokens. Contact your system administrator for token provisioning.