Daily Balances API
This page describes the implemented JSON REST API for exposing the data currently shown on the /history page.
Status:
- Implemented in
shift-planner-app.
Endpoint
GET /api/v1/warehouses/daily-balances?from=2026-03-01&to=2026-03-31&include_empty_days=false
Goal
The endpoint returns daily balance records across all warehouses for a requested date range.
The response is grouped by warehouse so clients do not need to de-duplicate warehouse metadata on each row.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
from |
string |
yes | Start date in YYYY-MM-DD format, inclusive. |
to |
string |
no | End date in YYYY-MM-DD format, inclusive. |
include_empty_days |
boolean |
no | If true, the API also returns missing days inside the requested range with zero-valued metrics. Default is false. |
Request Rules
frommust be a valid ISO date.tomust be a valid ISO date when provided.- If
tois missing, the API defaults it tofrom + 1 calendar month - 1 day. - The API rejects requests where
to < from. - The API rejects requests where the requested range is longer than
31days. - Warehouses are sorted by
warehouse.id. - Records inside each warehouse are sorted by
business_dateascending.
Response Design
The response contains only business-facing fields.
It intentionally does not expose:
- HTML-specific labels used by the
/historypage - internal editing links
- internal audit field
updated_by
When include_empty_days=false, the API returns only warehouses and dates that have stored records.
When include_empty_days=true, the API also fills missing dates with zero-valued metrics. For generated empty days, updated_at is null.
Response Shape
{
"data": [
{
"warehouse": {
"id": 1,
"name": "Jablonec"
},
"records": [
{
"business_date": "2026-03-03",
"metrics": {
"full_pallets": 1,
"full_roll_cages": 0,
"empty_pallets": 2,
"empty_roll_cages": 3,
"pallets_to_be_stocked": 3,
"dispatched_yesterday_pallets": 0,
"dispatched_yesterday_roll_cages": 20
},
"updated_at": "2026-03-04T13:40:09Z"
}
]
}
],
"meta": {
"filters": {
"from": "2026-03-01",
"to": "2026-03-31",
"include_empty_days": false
},
"warehouse_count": 1,
"record_count": 1
}
}
Field Definitions
Warehouse
| Field | Type | Description |
|---|---|---|
id |
integer |
Internal warehouse identifier used by Shift Planner. |
name |
string |
Warehouse display name. |
Record
| Field | Type | Description |
|---|---|---|
business_date |
string |
Business date in YYYY-MM-DD format. |
updated_at |
string \| null |
Last update timestamp in ISO 8601 UTC format. Generated empty days use null. |
metrics.full_pallets |
integer |
Number of full pallets. |
metrics.full_roll_cages |
integer |
Number of full roll cages. |
metrics.empty_pallets |
integer |
Number of empty pallets. |
metrics.empty_roll_cages |
integer |
Number of empty roll cages. |
metrics.pallets_to_be_stocked |
integer |
Number of pallets waiting to be stocked. |
metrics.dispatched_yesterday_pallets |
integer |
Number of pallets dispatched on the previous day. |
metrics.dispatched_yesterday_roll_cages |
integer |
Number of roll cages dispatched on the previous day. |
Example Request
GET /api/v1/warehouses/daily-balances?from=2026-03-01&to=2026-03-31&include_empty_days=false
Accept: application/json
Example Response
{
"data": [
{
"warehouse": {
"id": 1,
"name": "Jablonec"
},
"records": [
{
"business_date": "2026-03-03",
"metrics": {
"full_pallets": 1,
"full_roll_cages": 0,
"empty_pallets": 2,
"empty_roll_cages": 3,
"pallets_to_be_stocked": 3,
"dispatched_yesterday_pallets": 0,
"dispatched_yesterday_roll_cages": 20
},
"updated_at": "2026-03-04T13:40:09Z"
}
]
},
{
"warehouse": {
"id": 4,
"name": "Ceska Lipa"
},
"records": [
{
"business_date": "2026-03-04",
"metrics": {
"full_pallets": 3,
"full_roll_cages": 0,
"empty_pallets": 0,
"empty_roll_cages": 3,
"pallets_to_be_stocked": 0,
"dispatched_yesterday_pallets": 3,
"dispatched_yesterday_roll_cages": 3
},
"updated_at": "2026-03-04T13:54:56Z"
}
]
}
],
"meta": {
"filters": {
"from": "2026-03-01",
"to": "2026-03-31",
"include_empty_days": false
},
"warehouse_count": 2,
"record_count": 2
}
}
Example Response With Empty Days
{
"data": [
{
"warehouse": {
"id": 4,
"name": "Ceska Lipa"
},
"records": [
{
"business_date": "2026-03-03",
"metrics": {
"full_pallets": 7,
"full_roll_cages": 1,
"empty_pallets": 2,
"empty_roll_cages": 3,
"pallets_to_be_stocked": 4,
"dispatched_yesterday_pallets": 5,
"dispatched_yesterday_roll_cages": 6
},
"updated_at": "2026-03-03T06:00:00Z"
},
{
"business_date": "2026-03-04",
"metrics": {
"full_pallets": 0,
"full_roll_cages": 0,
"empty_pallets": 0,
"empty_roll_cages": 0,
"pallets_to_be_stocked": 0,
"dispatched_yesterday_pallets": 0,
"dispatched_yesterday_roll_cages": 0
},
"updated_at": null
}
]
}
],
"meta": {
"filters": {
"from": "2026-03-03",
"to": "2026-03-04",
"include_empty_days": true
},
"warehouse_count": 1,
"record_count": 2
}
}
Recommended Validation Errors
400 Bad Requestfor invalid date format400 Bad Requestfor missingfrom400 Bad Requestwhentois earlier thanfrom400 Bad Requestfor invalid boolean format ininclude_empty_days400 Bad Requestwhen the requested range exceeds31days
Notes
- This API is based on the current
/historydata model in the application. - The API uses English field names even though the current HTML page is Czech.
- The API is designed for integrations first, not for rendering the existing HTML table directly.