Overview
Base URL
All API requests should be made to:
https://demo.itglonline.com/api/v1
Authentication
Use Laravel Sanctum Bearer tokens. Include in all requests:
Authorization: Bearer {token}
Content Type
All requests and responses use JSON format:
Content-Type: application/json
Accept: application/json
Rate Limiting
Default limits per endpoint type:
Standard: 60/min
POS lookups: 120/min
Bulk operations: 10/min
Response Format
All API responses follow a consistent structure:
{
"success": true,
"data": { "...response data..." },
"meta": { "...pagination info (if applicable)..." }
}
{
"success": false,
"message": "Error description",
"errors": { "...validation errors (if applicable)..." }
}
Authentication
Authentication basics for API consumers.
Authenticate a user and receive an access token for API requests.
| Parameter | Type | Description |
|---|---|---|
| email *required | string | User email address |
| password *required | string | User password |
| device_name | string | Device identifier (default: "Mobile POS") |
| store_id | integer | Store to login to |
| two_factor_code | string | 2FA code if enabled |
{
"email": "cashier@store.com",
"password": "secret123",
"device_name": "iPhone 15 Pro",
"store_id": 1
}
{
"success": true,
"data": {
"token": "1|abc123xyz...",
"user": {
"id": 1,
"name": "John Doe",
"email": "cashier@store.com",
"role": {
"id": 2,
"name": "Cashier",
"slug": "cashier"
},
"store_id": 1,
"store_name": "Main Store",
"is_super_admin": false,
"has_two_factor": false
},
"permissions": [
"pos.access",
"sales.view",
"customers.view"
],
"store_id": 1
}
}
Retrieve the authenticated user profile, permissions, and discount limits.
{
"success": true,
"data": {
"id": 1,
"name": "John Doe",
"email": "cashier@store.com",
"role": {
"id": 2,
"name": "Cashier"
},
"store_id": 1,
"permissions": [
"pos.access",
"sales.view"
],
"discount_limits": {
"max_discount_percent": 15,
"max_discount_amount": 500
}
}
}
Integrations & Webhooks
Public integration consumer endpoints and outbound webhook signature contract. Webhook headers: X-NakPOS-Event, X-NakPOS-Timestamp, X-NakPOS-Signature, X-NakPOS-Delivery-Id. Signature: HMAC SHA-256 over "timestamp.raw_body".
Read-only sales export feed for API application users. Requires auth:sanctum + api.application + permission:sales.view + token ability sales:read. Alias path: /integrations/sales.
| Parameter | Type | Description |
|---|---|---|
| from | date | Start date (YYYY-MM-DD) |
| to | date | End date (YYYY-MM-DD) |
| status | string | Sale status |
| store_id | integer | Filter by store |
| warehouse_id | integer | Filter by warehouse |
| q | string | Search receipt/barcode/reference |
| per_page | integer | Items per page (default: 50, max: 200) |
{
"success": true,
"data": [
{
"id": 123,
"receipt_number": "RCP-20260212-0001",
"store": {
"id": 1,
"name": "Main Store"
},
"warehouse": {
"id": 2,
"name": "Main Sales Floor"
},
"status": "completed",
"total_amount": 1074.99,
"created_at": "2026-02-12T10: 30: 00Z"
}
],
"meta": {
"current_page": 1,
"last_page": 10,
"per_page": 50,
"total": 500
}
}
Get one sale with full store/warehouse context for downstream ingestion. Requires auth:sanctum + api.application + permission:sales.view + token ability sales:read. Alias path: /integrations/sales/{sale}.
{
"success": true,
"data": {
"id": 123,
"receipt_number": "RCP-20260212-0001",
"store": {
"id": 1,
"name": "Main Store"
},
"warehouse": {
"id": 2,
"name": "Main Sales Floor"
},
"items": [
"...line items..."
],
"payments": [
"...payment lines..."
],
"status": "completed"
}
}
Reporting
Build read-only reports from integration sales feeds. Use created_at consistently for time windows, group with store/warehouse objects, and handle nullable warehouse values.
Pull daily sales for status-based reporting. Alias path: /integrations/sales. Use this for daily totals and status rollups.
| Parameter | Type | Description |
|---|---|---|
| from | date | Start date (YYYY-MM-DD) |
| to | date | End date (YYYY-MM-DD) |
| status | string | Sale status filter for report slices |
| store_id | integer | Optional store filter |
| warehouse_id | integer | Optional warehouse filter |
| q | string | Free-text search on receipt/barcode/reference |
| per_page | integer | Items per page (default: 50, max: 200) |
{
"from": "2026-02-11",
"to": "2026-02-11",
"status": "completed",
"per_page": 200
}
{
"success": true,
"data": [
{
"id": 901,
"receipt_number": "RCP-20260211-0001",
"status": "completed",
"store": {
"id": 1,
"name": "Main Store"
},
"warehouse": {
"id": 2,
"name": "Sales Floor"
},
"total_amount": 245,
"created_at": "2026-02-11T09: 15: 00Z"
}
],
"meta": {
"current_page": 1,
"last_page": 3,
"per_page": 200,
"total": 467
}
}
Filter by store_id and aggregate totals externally for store-level performance reporting.
| Parameter | Type | Description |
|---|---|---|
| store_id *required | integer | Store ID for rollup |
| from | date | Start date |
| to | date | End date |
| per_page | integer | Items per page for batching |
{
"store_id": 1,
"from": "2026-02-01",
"to": "2026-02-12",
"per_page": 100
}
{
"success": true,
"data": [
{
"id": 950,
"receipt_number": "RCP-20260212-0212",
"store": {
"id": 1,
"name": "Main Store"
},
"warehouse": {
"id": 2,
"name": "Sales Floor"
},
"status": "completed",
"total_amount": 1080,
"created_at": "2026-02-12T17: 40: 00Z"
}
],
"meta": {
"current_page": 1,
"last_page": 6,
"per_page": 100,
"total": 581
}
}
Filter by warehouse_id for warehouse-level reporting. Warehouses can be null on some sales, so account for uncategorized rows.
| Parameter | Type | Description |
|---|---|---|
| warehouse_id *required | integer | Warehouse ID for grouping |
| from | date | Start date |
| to | date | End date |
| status | string | Optional status filter |
| per_page | integer | Items per page for batching |
{
"warehouse_id": 2,
"from": "2026-02-01",
"to": "2026-02-12",
"status": "completed"
}
{
"success": true,
"data": [
{
"id": 997,
"receipt_number": "RCP-20260212-0301",
"store": {
"id": 1,
"name": "Main Store"
},
"warehouse": {
"id": 2,
"name": "Sales Floor"
},
"status": "completed",
"total_amount": 320.5,
"created_at": "2026-02-12T19: 02: 00Z"
}
],
"meta": {
"current_page": 1,
"last_page": 2,
"per_page": 50,
"total": 95
}
}
Use sale detail lookups to reconcile line items/payments for records flagged during incremental reporting syncs.
{
"success": true,
"data": {
"id": 997,
"receipt_number": "RCP-20260212-0301",
"store": {
"id": 1,
"name": "Main Store"
},
"warehouse": {
"id": 2,
"name": "Sales Floor"
},
"status": "completed",
"items": [
"...line items..."
],
"payments": [
"...payment lines..."
],
"created_at": "2026-02-12T19: 02: 00Z"
}
}
Error Handling
HTTP Status Codes
The API uses standard HTTP status codes to indicate the success or failure of requests:
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | Request succeeded |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Invalid request data or checkout validation error |
| 401 | Unauthorized | Missing or invalid authentication token |
| 403 | Forbidden | User lacks permission for this action |
| 404 | Not Found | Resource not found |
| 409 | Conflict | Conflict (e.g., duplicate session) |
| 422 | Unprocessable Entity | Validation errors in request data |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Server Error | Internal server error |
Validation Error Response
When validation fails (422), the response includes field-specific errors:
{
"success": false,
"message": "The given data was invalid.",
"errors": {
"email": ["The email field is required."],
"password": ["The password must be at least 8 characters."]
}
}