Nodeflux Central
Statistics

API Reference: Statistics

Endpoint Statistics v2 untuk dashboard, widget, layout, skema analitik, query tabular, binding Detail Stream, dan ekspor PDF, plus endpoint agregat per analitik lama yang masih tersedia.

Semua endpoint memerlukan otentikasi. Untuk integrasi, kirim header X-Api-Key: <key> di setiap request tanpa header Authorization. Bearer token (Authorization: Bearer <access_token>, berlaku 30 menit) hanya untuk aplikasi yang menampilkan login Lenz ke penggunanya sendiri dan wajib menyertakan X-Integration-Signature. Basis URL mengikuti variabel lingkungan VITE_API_URL yang dikonfigurasi pada instalasi Lenz. Lihat Otentikasi untuk memilih jalur yang tepat.

Semua endpoint berada di bawah /api/statistics dan memakai resource RBAC statistics. Respons sukses dibungkus { "ok": true, "message": "...", "data": {...} }; respons gagal { "ok": false, "message": "...", "errors": [{ "code": "...", "message": "..." }] }. Kesalahan spesifikasi query dan widget membawa field (misalnya metrics[0]) dan, bila relevan, daftar nilai available. Filter stream_id selalu dibatasi ke stream yang boleh diakses akun pemanggil.

Alur integrasi yang umum: panggil Skema Analitik untuk mengetahui metrik, dimensi, filter, dan batas rentang setiap analitik; susun query_spec dan uji lewat Jalankan Query Statistik; lalu simpan sebagai widget pada dashboard lewat Buat Dashboard atau Tambah Widget.


CRUD Dashboard

Dashboard menyimpan filter bersama (filters) dan deklarasi stream_analytics untuk Detail Stream. Daftar mengembalikan dashboard privat milik pemanggil plus dashboard global; dashboard Bawaan (is_seeded) hanya-baca bagi semua orang dan dashboard global hanya dapat diubah superadmin.

Daftar Dashboard

GET
/api/statistics/dashboards

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Response Body

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/dashboards"
{  "ok": true,  "message": "dashboards retrieved",  "data": {    "dashboards": [      {        "id": "0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c",        "name": "Face Recognition",        "description": "FR dashboard: recognition volume, known/unknown split, attributes, streams, peak times.",        "filters": {          "time_range": {            "start": "2026-09-12",            "end": "2026-09-18",            "preset": "last_7d"          }        },        "widget_count": 13,        "stream_analytics": [          "NFV4-FRA",          "NFV4-FR",          "NFV4H-FR",          "NFV4H-WZMND-FR",          "NFV4H-MOBLE-FR",          "NFV4H-ISAPI-FR"        ],        "is_global": true,        "is_seeded": true,        "seed_key": "fr",        "is_enabled": true,        "created_by": 0,        "created_at": "2026-08-27T02:10:00Z",        "updated_at": "2026-09-17T01:00:00Z"      }    ]  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Detail Dashboard

GET
/api/statistics/dashboards/{id}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

id*string

ID dashboard (UUID).

Formatuuid

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/dashboards/0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c"
{  "ok": true,  "message": "dashboard retrieved",  "data": {    "dashboard": {      "id": "0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c",      "name": "Pemantauan lobi",      "description": "Kunjungan dan durasi tinggal di lobi utama",      "filters": {        "time_range": {          "start": "2026-09-12",          "end": "2026-09-18",          "preset": "last_7d"        },        "instance": "all",        "stream_ids": [          "stream-abc123"        ],        "analytic_ids": [          "NFV4-FRA"        ]      },      "widgets": [        {          "id": "6f1c2a1e-8b1e-4a7e-9c3d-2f1a5b6c7d8e",          "dashboard_id": "6904cee6-5a01-4acf-92d9-7e185cd226de",          "title": "Known faces",          "viz_kind": "scorecard",          "query_spec": {            "analytic": "FRA",            "sub_mode": "counting",            "metrics": [              "total_detections",              "known_faces"            ],            "dimensions": [              "status"            ],            "filters": {              "stream_id": {                "op": "in",                "value": [                  "stream-abc123"                ]              }            },            "time_range": {              "start": "2026-09-12",              "end": "2026-09-18",              "preset": "last_7d"            },            "granularity": "day",            "limit": 10          },          "viz_config": {            "showLegend": true,            "body": "string",            "donut": true,            "heatmapMode": "weekly",            "showCellValues": true,            "stacked": true,            "showCard": true,            "gaugeTarget": 0,            "gaugeMin": 0,            "gaugeMax": 0,            "gaugeWarning": 0,            "gaugeDanger": 0,            "showComparison": true,            "comparisonPeriod": "previous",            "orientation": "vertical",            "rank": "top",            "rankCount": 0,            "tabs": [              {                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",                "label": "Gender",                "widgets": [                  {                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",                    "title": "Distribution",                    "viz_kind": "line",                    "query_spec": {                      "analytic": "FRA",                      "sub_mode": "counting",                      "metrics": [                        "total_detections",                        "known_faces"                      ],                      "dimensions": [                        "status"                      ],                      "filters": {                        "stream_id": {                          "op": "in",                          "value": [                            "stream-abc123"                          ]                        }                      },                      "time_range": {                        "start": "2026-09-12",                        "end": "2026-09-18",                        "preset": "last_7d"                      },                      "granularity": "day",                      "limit": 10                    },                    "viz_config": {                      "showLegend": true,                      "body": "string",                      "donut": true,                      "heatmapMode": "weekly",                      "showCellValues": true,                      "stacked": true,                      "showCard": true,                      "gaugeTarget": 0,                      "gaugeMin": 0,                      "gaugeMax": 0,                      "gaugeWarning": 0,                      "gaugeDanger": 0,                      "showComparison": true,                      "comparisonPeriod": "previous",                      "orientation": "vertical",                      "rank": "top",                      "rankCount": 0,                      "tabs": []                    },                    "layout": {                      "x": 0,                      "y": 2,                      "w": 4,                      "h": 6                    }                  }                ]              }            ]          },          "layout": {            "x": 0,            "y": 2,            "w": 4,            "h": 6          },          "created_at": "2019-08-24T14:15:22Z",          "updated_at": "2019-08-24T14:15:22Z"        }      ],      "widget_count": 13,      "stream_analytics": [        "NFV4-FRA",        "NFV4-FR"      ],      "is_global": true,      "is_seeded": true,      "seed_key": "fr",      "is_enabled": true,      "created_by": 0,      "created_at": "2019-08-24T14:15:22Z",      "updated_at": "2019-08-24T14:15:22Z"    }  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Buat Dashboard

POST
/api/statistics/dashboards

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

curl -X POST "https://lenz.example.com/api/statistics/dashboards" \  -H "Content-Type: application/json" \  -d '{    "name": "Pemantauan lobi",    "description": "Kunjungan dan durasi tinggal di lobi utama",    "filters": {      "time_range": {        "start": "2026-09-12",        "end": "2026-09-18",        "preset": "last_7d"      },      "stream_ids": [        "stream-lobby-01"      ]    },    "stream_analytics": [      "NFV4-MPAA:counting",      "NFV4-MPA2:counting"    ]  }'
{  "ok": true,  "message": "dashboard created",  "data": {    "dashboard": {      "id": "0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c",      "name": "Pemantauan lobi",      "description": "Kunjungan dan durasi tinggal di lobi utama",      "filters": {        "time_range": {          "start": "2026-09-12",          "end": "2026-09-18",          "preset": "last_7d"        },        "instance": "all",        "stream_ids": [          "stream-abc123"        ],        "analytic_ids": [          "NFV4-FRA"        ]      },      "widgets": [        {          "id": "6f1c2a1e-8b1e-4a7e-9c3d-2f1a5b6c7d8e",          "dashboard_id": "6904cee6-5a01-4acf-92d9-7e185cd226de",          "title": "Known faces",          "viz_kind": "scorecard",          "query_spec": {            "analytic": "FRA",            "sub_mode": "counting",            "metrics": [              "total_detections",              "known_faces"            ],            "dimensions": [              "status"            ],            "filters": {              "stream_id": {                "op": "in",                "value": [                  "stream-abc123"                ]              }            },            "time_range": {              "start": "2026-09-12",              "end": "2026-09-18",              "preset": "last_7d"            },            "granularity": "day",            "limit": 10          },          "viz_config": {            "showLegend": true,            "body": "string",            "donut": true,            "heatmapMode": "weekly",            "showCellValues": true,            "stacked": true,            "showCard": true,            "gaugeTarget": 0,            "gaugeMin": 0,            "gaugeMax": 0,            "gaugeWarning": 0,            "gaugeDanger": 0,            "showComparison": true,            "comparisonPeriod": "previous",            "orientation": "vertical",            "rank": "top",            "rankCount": 0,            "tabs": [              {                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",                "label": "Gender",                "widgets": [                  {                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",                    "title": "Distribution",                    "viz_kind": "line",                    "query_spec": {                      "analytic": "FRA",                      "sub_mode": "counting",                      "metrics": [                        "total_detections",                        "known_faces"                      ],                      "dimensions": [                        "status"                      ],                      "filters": {                        "stream_id": {                          "op": "in",                          "value": [                            "stream-abc123"                          ]                        }                      },                      "time_range": {                        "start": "2026-09-12",                        "end": "2026-09-18",                        "preset": "last_7d"                      },                      "granularity": "day",                      "limit": 10                    },                    "viz_config": {                      "showLegend": true,                      "body": "string",                      "donut": true,                      "heatmapMode": "weekly",                      "showCellValues": true,                      "stacked": true,                      "showCard": true,                      "gaugeTarget": 0,                      "gaugeMin": 0,                      "gaugeMax": 0,                      "gaugeWarning": 0,                      "gaugeDanger": 0,                      "showComparison": true,                      "comparisonPeriod": "previous",                      "orientation": "vertical",                      "rank": "top",                      "rankCount": 0,                      "tabs": []                    },                    "layout": {                      "x": 0,                      "y": 2,                      "w": 4,                      "h": 6                    }                  }                ]              }            ]          },          "layout": {            "x": 0,            "y": 2,            "w": 4,            "h": 6          },          "created_at": "2019-08-24T14:15:22Z",          "updated_at": "2019-08-24T14:15:22Z"        }      ],      "widget_count": 13,      "stream_analytics": [        "NFV4-FRA",        "NFV4-FR"      ],      "is_global": true,      "is_seeded": true,      "seed_key": "fr",      "is_enabled": true,      "created_by": 0,      "created_at": "2019-08-24T14:15:22Z",      "updated_at": "2019-08-24T14:15:22Z"    }  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Update Dashboard

PUT
/api/statistics/dashboards/{id}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

id*string

ID dashboard (UUID).

Formatuuid

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X PUT "https://lenz.example.com/api/statistics/dashboards/0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c" \  -H "Content-Type: application/json" \  -d '{    "name": "Pemantauan lobi",    "description": "Kunjungan dan durasi tinggal di lobi utama",    "filters": {      "time_range": {        "start": "2026-09-12",        "end": "2026-09-18",        "preset": "last_7d"      },      "stream_ids": [        "stream-lobby-01"      ]    },    "stream_analytics": [      "NFV4-MPAA:counting",      "NFV4-MPA2:counting"    ]  }'
{  "ok": true,  "message": "dashboard updated",  "data": {    "dashboard": {      "id": "0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c",      "name": "Pemantauan lobi",      "description": "Kunjungan dan durasi tinggal di lobi utama",      "filters": {        "time_range": {          "start": "2026-09-12",          "end": "2026-09-18",          "preset": "last_7d"        },        "instance": "all",        "stream_ids": [          "stream-abc123"        ],        "analytic_ids": [          "NFV4-FRA"        ]      },      "widgets": [        {          "id": "6f1c2a1e-8b1e-4a7e-9c3d-2f1a5b6c7d8e",          "dashboard_id": "6904cee6-5a01-4acf-92d9-7e185cd226de",          "title": "Known faces",          "viz_kind": "scorecard",          "query_spec": {            "analytic": "FRA",            "sub_mode": "counting",            "metrics": [              "total_detections",              "known_faces"            ],            "dimensions": [              "status"            ],            "filters": {              "stream_id": {                "op": "in",                "value": [                  "stream-abc123"                ]              }            },            "time_range": {              "start": "2026-09-12",              "end": "2026-09-18",              "preset": "last_7d"            },            "granularity": "day",            "limit": 10          },          "viz_config": {            "showLegend": true,            "body": "string",            "donut": true,            "heatmapMode": "weekly",            "showCellValues": true,            "stacked": true,            "showCard": true,            "gaugeTarget": 0,            "gaugeMin": 0,            "gaugeMax": 0,            "gaugeWarning": 0,            "gaugeDanger": 0,            "showComparison": true,            "comparisonPeriod": "previous",            "orientation": "vertical",            "rank": "top",            "rankCount": 0,            "tabs": [              {                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",                "label": "Gender",                "widgets": [                  {                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",                    "title": "Distribution",                    "viz_kind": "line",                    "query_spec": {                      "analytic": "FRA",                      "sub_mode": "counting",                      "metrics": [                        "total_detections",                        "known_faces"                      ],                      "dimensions": [                        "status"                      ],                      "filters": {                        "stream_id": {                          "op": "in",                          "value": [                            "stream-abc123"                          ]                        }                      },                      "time_range": {                        "start": "2026-09-12",                        "end": "2026-09-18",                        "preset": "last_7d"                      },                      "granularity": "day",                      "limit": 10                    },                    "viz_config": {                      "showLegend": true,                      "body": "string",                      "donut": true,                      "heatmapMode": "weekly",                      "showCellValues": true,                      "stacked": true,                      "showCard": true,                      "gaugeTarget": 0,                      "gaugeMin": 0,                      "gaugeMax": 0,                      "gaugeWarning": 0,                      "gaugeDanger": 0,                      "showComparison": true,                      "comparisonPeriod": "previous",                      "orientation": "vertical",                      "rank": "top",                      "rankCount": 0,                      "tabs": []                    },                    "layout": {                      "x": 0,                      "y": 2,                      "w": 4,                      "h": 6                    }                  }                ]              }            ]          },          "layout": {            "x": 0,            "y": 2,            "w": 4,            "h": 6          },          "created_at": "2019-08-24T14:15:22Z",          "updated_at": "2019-08-24T14:15:22Z"        }      ],      "widget_count": 13,      "stream_analytics": [        "NFV4-FRA",        "NFV4-FR"      ],      "is_global": true,      "is_seeded": true,      "seed_key": "fr",      "is_enabled": true,      "created_by": 0,      "created_at": "2019-08-24T14:15:22Z",      "updated_at": "2019-08-24T14:15:22Z"    }  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Hapus Dashboard

DELETE
/api/statistics/dashboards/{id}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

id*string

ID dashboard (UUID).

Formatuuid

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X DELETE "https://lenz.example.com/api/statistics/dashboards/0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c"
{  "ok": true,  "message": "dashboard deleted",  "data": {}}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Sembunyikan / Tampilkan Dashboard Global

PUT
/api/statistics/dashboards/{id}/enabled

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

id*string

ID dashboard (UUID).

Formatuuid

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

enabled*boolean

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X PUT "https://lenz.example.com/api/statistics/dashboards/0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c/enabled" \  -H "Content-Type: application/json" \  -d '{    "enabled": false  }'
{  "ok": true,  "message": "dashboard disabled",  "data": {    "dashboard": {      "id": "0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c",      "name": "Pemantauan lobi",      "description": "Kunjungan dan durasi tinggal di lobi utama",      "filters": {        "time_range": {          "start": "2026-09-12",          "end": "2026-09-18",          "preset": "last_7d"        },        "instance": "all",        "stream_ids": [          "stream-abc123"        ],        "analytic_ids": [          "NFV4-FRA"        ]      },      "widgets": [        {          "id": "6f1c2a1e-8b1e-4a7e-9c3d-2f1a5b6c7d8e",          "dashboard_id": "6904cee6-5a01-4acf-92d9-7e185cd226de",          "title": "Known faces",          "viz_kind": "scorecard",          "query_spec": {            "analytic": "FRA",            "sub_mode": "counting",            "metrics": [              "total_detections",              "known_faces"            ],            "dimensions": [              "status"            ],            "filters": {              "stream_id": {                "op": "in",                "value": [                  "stream-abc123"                ]              }            },            "time_range": {              "start": "2026-09-12",              "end": "2026-09-18",              "preset": "last_7d"            },            "granularity": "day",            "limit": 10          },          "viz_config": {            "showLegend": true,            "body": "string",            "donut": true,            "heatmapMode": "weekly",            "showCellValues": true,            "stacked": true,            "showCard": true,            "gaugeTarget": 0,            "gaugeMin": 0,            "gaugeMax": 0,            "gaugeWarning": 0,            "gaugeDanger": 0,            "showComparison": true,            "comparisonPeriod": "previous",            "orientation": "vertical",            "rank": "top",            "rankCount": 0,            "tabs": [              {                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",                "label": "Gender",                "widgets": [                  {                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",                    "title": "Distribution",                    "viz_kind": "line",                    "query_spec": {                      "analytic": "FRA",                      "sub_mode": "counting",                      "metrics": [                        "total_detections",                        "known_faces"                      ],                      "dimensions": [                        "status"                      ],                      "filters": {                        "stream_id": {                          "op": "in",                          "value": [                            "stream-abc123"                          ]                        }                      },                      "time_range": {                        "start": "2026-09-12",                        "end": "2026-09-18",                        "preset": "last_7d"                      },                      "granularity": "day",                      "limit": 10                    },                    "viz_config": {                      "showLegend": true,                      "body": "string",                      "donut": true,                      "heatmapMode": "weekly",                      "showCellValues": true,                      "stacked": true,                      "showCard": true,                      "gaugeTarget": 0,                      "gaugeMin": 0,                      "gaugeMax": 0,                      "gaugeWarning": 0,                      "gaugeDanger": 0,                      "showComparison": true,                      "comparisonPeriod": "previous",                      "orientation": "vertical",                      "rank": "top",                      "rankCount": 0,                      "tabs": []                    },                    "layout": {                      "x": 0,                      "y": 2,                      "w": 4,                      "h": 6                    }                  }                ]              }            ]          },          "layout": {            "x": 0,            "y": 2,            "w": 4,            "h": 6          },          "created_at": "2019-08-24T14:15:22Z",          "updated_at": "2019-08-24T14:15:22Z"        }      ],      "widget_count": 13,      "stream_analytics": [        "NFV4-FRA",        "NFV4-FR"      ],      "is_global": true,      "is_seeded": true,      "seed_key": "fr",      "is_enabled": true,      "created_by": 0,      "created_at": "2019-08-24T14:15:22Z",      "updated_at": "2019-08-24T14:15:22Z"    }  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Widget & Layout

Widget dibuat, diubah, dan dihapus satu per satu; posisi banyak widget disimpan sekaligus lewat endpoint Layout. Setiap query_spec divalidasi terhadap skema analitik dan aturan visualisasi viz_kind sebelum disimpan.

Tambah Widget

POST
/api/statistics/dashboards/{id}/widgets

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

id*string

ID dashboard (UUID).

Formatuuid

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://lenz.example.com/api/statistics/dashboards/0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c/widgets" \  -H "Content-Type: application/json" \  -d '{    "title": "Known faces",    "viz_kind": "scorecard",    "query_spec": {      "analytic": "FRA",      "metrics": [        "known_faces"      ],      "dimensions": [],      "granularity": ""    },    "viz_config": {},    "layout": {      "x": 3,      "y": 2,      "w": 3,      "h": 4    }  }'
{  "ok": true,  "message": "widget created",  "data": {    "widget": {      "id": "6f1c2a1e-8b1e-4a7e-9c3d-2f1a5b6c7d8e",      "dashboard_id": "6904cee6-5a01-4acf-92d9-7e185cd226de",      "title": "Known faces",      "viz_kind": "scorecard",      "query_spec": {        "analytic": "FRA",        "sub_mode": "counting",        "metrics": [          "total_detections",          "known_faces"        ],        "dimensions": [          "status"        ],        "filters": {          "stream_id": {            "op": "in",            "value": [              "stream-abc123"            ]          }        },        "time_range": {          "start": "2026-09-12",          "end": "2026-09-18",          "preset": "last_7d"        },        "granularity": "day",        "limit": 10      },      "viz_config": {        "showLegend": true,        "body": "string",        "donut": true,        "heatmapMode": "weekly",        "showCellValues": true,        "stacked": true,        "showCard": true,        "gaugeTarget": 0,        "gaugeMin": 0,        "gaugeMax": 0,        "gaugeWarning": 0,        "gaugeDanger": 0,        "showComparison": true,        "comparisonPeriod": "previous",        "orientation": "vertical",        "rank": "top",        "rankCount": 0,        "tabs": [          {            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",            "label": "Gender",            "widgets": [              {                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",                "title": "Distribution",                "viz_kind": "line",                "query_spec": {                  "analytic": "FRA",                  "sub_mode": "counting",                  "metrics": [                    "total_detections",                    "known_faces"                  ],                  "dimensions": [                    "status"                  ],                  "filters": {                    "stream_id": {                      "op": "in",                      "value": [                        "stream-abc123"                      ]                    }                  },                  "time_range": {                    "start": "2026-09-12",                    "end": "2026-09-18",                    "preset": "last_7d"                  },                  "granularity": "day",                  "limit": 10                },                "viz_config": {                  "showLegend": true,                  "body": "string",                  "donut": true,                  "heatmapMode": "weekly",                  "showCellValues": true,                  "stacked": true,                  "showCard": true,                  "gaugeTarget": 0,                  "gaugeMin": 0,                  "gaugeMax": 0,                  "gaugeWarning": 0,                  "gaugeDanger": 0,                  "showComparison": true,                  "comparisonPeriod": "previous",                  "orientation": "vertical",                  "rank": "top",                  "rankCount": 0,                  "tabs": []                },                "layout": {                  "x": 0,                  "y": 2,                  "w": 4,                  "h": 6                }              }            ]          }        ]      },      "layout": {        "x": 0,        "y": 2,        "w": 4,        "h": 6      },      "created_at": "2019-08-24T14:15:22Z",      "updated_at": "2019-08-24T14:15:22Z"    }  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Update Widget

PUT
/api/statistics/dashboards/{id}/widgets/{widgetId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

id*string

ID dashboard (UUID).

Formatuuid
widgetId*string

ID widget (UUID).

Formatuuid

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X PUT "https://lenz.example.com/api/statistics/dashboards/0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c/widgets/6f1c2a1e-8b1e-4a7e-9c3d-2f1a5b6c7d8e" \  -H "Content-Type: application/json" \  -d '{    "title": "Known faces",    "viz_kind": "scorecard",    "query_spec": {      "analytic": "FRA",      "metrics": [        "known_faces"      ],      "dimensions": [],      "granularity": ""    },    "viz_config": {},    "layout": {      "x": 3,      "y": 2,      "w": 3,      "h": 4    }  }'
{  "ok": true,  "message": "widget updated",  "data": {    "widget": {      "id": "6f1c2a1e-8b1e-4a7e-9c3d-2f1a5b6c7d8e",      "dashboard_id": "6904cee6-5a01-4acf-92d9-7e185cd226de",      "title": "Known faces",      "viz_kind": "scorecard",      "query_spec": {        "analytic": "FRA",        "sub_mode": "counting",        "metrics": [          "total_detections",          "known_faces"        ],        "dimensions": [          "status"        ],        "filters": {          "stream_id": {            "op": "in",            "value": [              "stream-abc123"            ]          }        },        "time_range": {          "start": "2026-09-12",          "end": "2026-09-18",          "preset": "last_7d"        },        "granularity": "day",        "limit": 10      },      "viz_config": {        "showLegend": true,        "body": "string",        "donut": true,        "heatmapMode": "weekly",        "showCellValues": true,        "stacked": true,        "showCard": true,        "gaugeTarget": 0,        "gaugeMin": 0,        "gaugeMax": 0,        "gaugeWarning": 0,        "gaugeDanger": 0,        "showComparison": true,        "comparisonPeriod": "previous",        "orientation": "vertical",        "rank": "top",        "rankCount": 0,        "tabs": [          {            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",            "label": "Gender",            "widgets": [              {                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",                "title": "Distribution",                "viz_kind": "line",                "query_spec": {                  "analytic": "FRA",                  "sub_mode": "counting",                  "metrics": [                    "total_detections",                    "known_faces"                  ],                  "dimensions": [                    "status"                  ],                  "filters": {                    "stream_id": {                      "op": "in",                      "value": [                        "stream-abc123"                      ]                    }                  },                  "time_range": {                    "start": "2026-09-12",                    "end": "2026-09-18",                    "preset": "last_7d"                  },                  "granularity": "day",                  "limit": 10                },                "viz_config": {                  "showLegend": true,                  "body": "string",                  "donut": true,                  "heatmapMode": "weekly",                  "showCellValues": true,                  "stacked": true,                  "showCard": true,                  "gaugeTarget": 0,                  "gaugeMin": 0,                  "gaugeMax": 0,                  "gaugeWarning": 0,                  "gaugeDanger": 0,                  "showComparison": true,                  "comparisonPeriod": "previous",                  "orientation": "vertical",                  "rank": "top",                  "rankCount": 0,                  "tabs": []                },                "layout": {                  "x": 0,                  "y": 2,                  "w": 4,                  "h": 6                }              }            ]          }        ]      },      "layout": {        "x": 0,        "y": 2,        "w": 4,        "h": 6      },      "created_at": "2019-08-24T14:15:22Z",      "updated_at": "2019-08-24T14:15:22Z"    }  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Hapus Widget

DELETE
/api/statistics/dashboards/{id}/widgets/{widgetId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

id*string

ID dashboard (UUID).

Formatuuid
widgetId*string

ID widget (UUID).

Formatuuid

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X DELETE "https://lenz.example.com/api/statistics/dashboards/0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c/widgets/6f1c2a1e-8b1e-4a7e-9c3d-2f1a5b6c7d8e"
{  "ok": true,  "message": "widget deleted",  "data": {}}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Update Layout Widget

PUT
/api/statistics/dashboards/{id}/layouts

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

id*string

ID dashboard (UUID).

Formatuuid

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X PUT "https://lenz.example.com/api/statistics/dashboards/0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c/layouts" \  -H "Content-Type: application/json" \  -d '{    "layouts": {      "6f1c2a1e-8b1e-4a7e-9c3d-2f1a5b6c7d8e": {        "x": 0,        "y": 2,        "w": 3,        "h": 4      },      "a3d4e5f6-1b2c-4d5e-8f90-abcdefabcdef": {        "x": 3,        "y": 2,        "w": 9,        "h": 8      }    }  }'
{  "ok": true,  "message": "layouts updated",  "data": {}}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Skema & Query

Skema adalah sumber kebenaran untuk menyusun query: ID analitik (FRA, LPR, MPA, MVA, CE, PPE, GENERAL), metrik beserta kelas agregasinya, dimensi dan filter beserta nilai enum, granularitas yang didukung, batas lebar rentang, dan sub-mode. Endpoint Query mengembalikan tabel columns + rows yang sama untuk semua jenis visualisasi; parameter instance dan is_aggregated mengaktifkan mode Federation.

Skema Analitik

GET
/api/statistics/schema

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

analytic?string

Batasi ke satu analitik: FRA, LPR, MPA, MVA, CE, PPE, atau GENERAL.

instance?string

Mode Federation: ID instance tujuan, atau beberapa ID dipisah koma untuk fan-out terbatas yang hasilnya digabung. Kosong berarti instance host.

is_aggregated?boolean

Mode Federation: true menjalankan query di seluruh instance dan menggabungkan hasilnya (setara instance=all pada filter dashboard).

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/schema?analytic=MPA&instance=remote-jakarta"
{  "ok": true,  "message": "schema retrieved",  "data": {    "analytics": [      {        "id": "MPA",        "label": "People Analytics",        "metrics": [          {            "id": "total_detections",            "label": "Total detections",            "unit": "count",            "aggregation": "additive",            "sub_mode": "string",            "requires_mpa2": true          }        ],        "dimensions": [          {            "id": "gender",            "label": "Gender",            "type": "string",            "options": [              "Female",              "Male"            ],            "sub_mode": "string",            "requires_mpa2": true          }        ],        "filters": [          {            "id": "status",            "label": "Status",            "type": "string",            "operator": "in",            "options": [              "string"            ],            "sub_mode": "string",            "requires_mpa2": true          }        ],        "granularities": [          "hour",          "day",          "week",          "month",          "quarter",          "year"        ],        "max_range_days": {          "": 730,          "hour": 31,          "day": 365,          "week": 730,          "month": 730,          "quarter": 730,          "year": 730        },        "sub_modes": [          {            "id": "counting",            "label": "People Counting"          }        ],        "default_sub_mode": "counting"      }    ],    "viz_kinds": [      {        "kind": "line",        "min_metrics": 1,        "max_metrics": 4,        "granularity": "required",        "max_breakdown_dims": 1,        "requires_limit": true,        "axis_min": 0,        "axis_max": 0,        "series_forces_single_metric": true      }    ]  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Varian Analitik

GET
/api/statistics/analytic-variants

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

analytic*string

ID analitik pada registry.

instance?string

Mode Federation: ID instance tujuan, atau beberapa ID dipisah koma untuk fan-out terbatas yang hasilnya digabung. Kosong berarti instance host.

is_aggregated?boolean

Mode Federation: true menjalankan query di seluruh instance dan menggabungkan hasilnya (setara instance=all pada filter dashboard).

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/analytic-variants?analytic=FRA&instance=remote-jakarta"
{  "ok": true,  "message": "analytic variants retrieved",  "data": {    "analytic": "FRA",    "variants": [      "NFV4-FRA",      "NFV4-FR",      "NFV4H-FR",      "NFV4H-WZMND-FR",      "NFV4H-MOBLE-FR",      "NFV4H-ISAPI-FR"    ]  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Jalankan Query Statistik

POST
/api/statistics/query

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

instance?string

Mode Federation: ID instance tujuan, atau beberapa ID dipisah koma untuk fan-out terbatas yang hasilnya digabung. Kosong berarti instance host.

is_aggregated?boolean

Mode Federation: true menjalankan query di seluruh instance dan menggabungkan hasilnya (setara instance=all pada filter dashboard).

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://lenz.example.com/api/statistics/query?instance=remote-jakarta" \  -H "Content-Type: application/json" \  -d '{    "analytic": "FRA",    "metrics": [      "total_detections"    ],    "dimensions": [      "status"    ],    "granularity": "day",    "time_range": {      "start": "2026-09-12",      "end": "2026-09-18"    },    "filters": {      "stream_id": {        "op": "in",        "value": [          "stream-lobby-01"        ]      }    },    "viz_kind": "line"  }'
{  "ok": true,  "message": "query executed",  "data": {    "columns": [      {        "id": "bucket",        "label": "Time",        "type": "timestamp",        "agg": "bucket"      },      {        "id": "status",        "label": "Status",        "type": "string",        "agg": "dimension"      },      {        "id": "total_detections",        "label": "Total detections",        "type": "int",        "agg": "additive"      }    ],    "rows": [      [        "2026-09-12T00:00:00+07:00",        "KNOWN",        412      ],      [        "2026-09-12T00:00:00+07:00",        "UNKNOWN",        96      ],      [        "2026-09-13T00:00:00+07:00",        "KNOWN",        388      ],      [        "2026-09-13T00:00:00+07:00",        "UNKNOWN",        121      ]    ],    "meta": {      "view_refreshed_at": "2026-09-18T09:00:12+07:00",      "row_count": 4,      "truncated": false,      "granularity": "day",      "timezone": "Asia/Jakarta",      "partial_bucket": "2026-09-18T00:00:00+07:00"    }  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Binding Detail Stream

Menentukan dashboard mana yang ditampilkan pada kartu Dashboard Statistik di halaman detail satu stream. Binding bersifat global per stream; dashboard yang dipilih harus terlihat oleh pemanggil dan tidak disembunyikan.

Dashboard Terpilih untuk Stream

GET
/api/statistics/stream-bindings/{streamId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

streamId*string

ID stream (stream_id Visionaire).

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/stream-bindings/stream-lobby-01"
{  "ok": true,  "message": "stream binding retrieved",  "data": {    "binding": {      "stream_id": "stream-lobby-01",      "dashboard_id": "0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c",      "updated_at": "2026-09-18T08:00:00Z"    }  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Pilih Dashboard untuk Stream

PUT
/api/statistics/stream-bindings/{streamId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

streamId*string

ID stream (stream_id Visionaire).

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X PUT "https://lenz.example.com/api/statistics/stream-bindings/stream-lobby-01" \  -H "Content-Type: application/json" \  -d '{    "dashboard_id": "0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c"  }'
{  "ok": true,  "message": "stream binding saved",  "data": {    "binding": {      "stream_id": "stream-lobby-01",      "dashboard_id": "6904cee6-5a01-4acf-92d9-7e185cd226de",      "updated_at": "2019-08-24T14:15:22Z"    }  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Hapus Pilihan Dashboard Stream

DELETE
/api/statistics/stream-bindings/{streamId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

streamId*string

ID stream (stream_id Visionaire).

Response Body

application/json

application/json

application/json

application/json

curl -X DELETE "https://lenz.example.com/api/statistics/stream-bindings/stream-lobby-01"
{  "ok": true,  "message": "stream binding removed",  "data": {    "binding": null  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Ekspor PDF Dashboard

Ekspor berjalan asinkron: inisiasi mengembalikan job_id, poll status sampai completed, lalu unduh file. File tersedia selama 24 jam. Di UI, alur ini dipantau lewat Pusat Tugas.

Inisiasi Ekspor PDF

POST
/api/statistics/dashboards/{id}/export

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

id*string

ID dashboard (UUID).

Formatuuid

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://lenz.example.com/api/statistics/dashboards/0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c/export" \  -H "Content-Type: application/json" \  -d '{    "filters": {      "time_range": {        "start": "2026-09-12",        "end": "2026-09-18"      },      "stream_ids": [        "stream-lobby-01"      ]    }  }'
{  "ok": true,  "message": "export initiated",  "data": {    "job_id": "3e0f9c1a-7b2d-4c5e-8f6a-1b2c3d4e5f60"  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Status Job Ekspor

GET
/api/statistics/dashboards/{id}/export/{jobId}/status

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

id*string

ID dashboard (UUID).

Formatuuid
jobId*string

ID job ekspor yang dikembalikan saat inisiasi.

Formatuuid

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/dashboards/0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c/export/3e0f9c1a-7b2d-4c5e-8f6a-1b2c3d4e5f60/status"
{  "ok": true,  "message": "export status",  "data": {    "status": "completed",    "progress": 100,    "file_ready": true  }}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Unduh PDF

GET
/api/statistics/dashboards/{id}/export/{jobId}/download

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

id*string

ID dashboard (UUID).

Formatuuid
jobId*string

ID job ekspor yang dikembalikan saat inisiasi.

Formatuuid

Response Body

application/pdf

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/dashboards/0b7a3e2c-1d4f-4e6a-9b8c-5d6e7f8a9b0c/export/3e0f9c1a-7b2d-4c5e-8f6a-1b2c3d4e5f60/download"
"string"
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}
{  "ok": false,  "message": "invalid query spec",  "errors": [    {      "code": "RANGE_TOO_WIDE",      "field": "time_range",      "message": "granularity 'hour' supports up to 31 days; got 45",      "available": [        "hour",        "day",        "week",        "month",        "quarter",        "year"      ]    }  ]}

Endpoint Legacy per Analitik

Endpoint agregat generasi sebelumnya masih dilayani untuk kompatibilitas integrasi yang sudah berjalan dan menjadi sumber data halaman /statistics-old. Setiap endpoint mengembalikan satu paket metrik tetap per analitik berdasarkan stream_id, start_date, dan end_date. Untuk integrasi baru, gunakan Jalankan Query Statistik yang mencakup semua analitik dengan bentuk respons seragam.

Face Recognition

GET
/api/statistics/fr

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string

ID stream, pisahkan dengan koma untuk beberapa stream

start_date*string

Tanggal mulai (YYYY-MM-DD)

Formatdate
end_date*string

Tanggal akhir (YYYY-MM-DD)

Formatdate
instance?string

ID instance pada mode Federation

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/fr?stream_id=stream-abc123%2Cstream-def456&start_date=2025-04-01&end_date=2025-04-07"
{  "ok": true,  "message": "success",  "data": {    "time_range": "hourly",    "start_date": "2025-04-01",    "end_date": "2025-04-07",    "summary": {      "known": 480,      "unknown": 120,      "total": 600,      "total_detections": 850,      "known_percentage": 80,      "unknown_percentage": 20    },    "time_series_data": [      {        "time_label": "09:00",        "event_time": "2025-04-01T09:00:00+07:00",        "known": 50,        "unknown": 10,        "total": 60,        "total_detections": 80,        "percent_of_total": 12.5,        "change_from_previous": 5      }    ],    "stream_distribution": [      {        "stream_id": "stream-abc123",        "stream_name": "Lobby Utama",        "location": "Gedung A",        "percent_of_total": 38.5,        "known": 200,        "unknown": 50,        "total": 250,        "total_detections": 320      }    ],    "peak_time_info": {      "peak_time": "14:00",      "peak_count": 132,      "lowest_time": "03:00",      "lowest_count": 2    },    "trends": {      "overall_trend": "increasing",      "average_per_interval": 45.3,      "peak_to_average_ratio": 2.9    },    "timestamp": "2019-08-24T14:15:22Z"  }}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
GET
/api/statistics/fra

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string

ID stream, pisahkan dengan koma untuk beberapa stream

start_date*string
Formatdate
end_date*string
Formatdate
analytic_id?string

Filter berdasarkan tipe analitik, contoh: NFV4-FRA, NFV4H-WZMND-FR, NFV4H-MOBLE-FR

instance?string

ID instance pada mode Federation

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/fra?stream_id=stream-abc123&start_date=2025-04-01&end_date=2025-04-30&analytic_id=NFV4-FRA"
{  "message": "success",  "data": {    "time_range": "daily",    "start_date": "2025-04-01",    "end_date": "2025-04-30",    "summary": {      "known": 480,      "unknown": 120,      "total": 600,      "total_detections": 850,      "known_percentage": 80,      "unknown_percentage": 20,      "demographics": {        "male_count": 300,        "female_count": 180,        "adult_count": 420,        "child_count": 60,        "mask_count": 45,        "no_mask_count": 435,        "glasses_count": 120,        "no_glasses_count": 360,        "head_covering_count": 30,        "no_head_covering_count": 450,        "male_percentage": 62.5,        "female_percentage": 37.5,        "adult_percentage": 87.5,        "child_percentage": 12.5,        "mask_percentage": 9.4,        "no_mask_percentage": 90.6,        "glasses_percentage": 25,        "no_glasses_percentage": 75,        "head_covering_percentage": 6.25      }    },    "time_series_data": [      {        "time_label": "09:00",        "event_time": "2025-04-01T09:00:00+07:00",        "known": 50,        "unknown": 10,        "total": 60,        "total_detections": 80,        "percent_of_total": 12.5,        "change_from_previous": 5,        "male_count": 30,        "female_count": 20,        "adult_count": 45,        "child_count": 5,        "mask_count": 3,        "no_mask_count": 47,        "glasses_count": 12,        "no_glasses_count": 38,        "head_covering_count": 2,        "no_head_covering_count": 48      }    ],    "stream_distribution": [      {        "stream_id": "stream-abc123",        "stream_name": "Lobby Utama",        "location": "Gedung A",        "percent_of_total": 38.5,        "known": 200,        "unknown": 50,        "total": 250,        "total_detections": 320      }    ],    "peak_time_info": {      "peak_time": "14:00",      "peak_count": 132,      "lowest_time": "03:00",      "lowest_count": 2    },    "trends": {      "overall_trend": "increasing",      "average_per_interval": 45.3,      "peak_to_average_ratio": 2.9    },    "timestamp": "2019-08-24T14:15:22Z"  }}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}

License Plate Recognition

GET
/api/statistics/lpr2

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string

ID stream, pisahkan dengan koma untuk beberapa stream

start_date*string
Formatdate
end_date*string
Formatdate
analytic_id?string

Filter tipe analitik LPR, contoh: NFV4-LPR2, NFV4-LPR3

instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/lpr2?stream_id=stream-gate01%2Cstream-gate02&start_date=2025-04-01&end_date=2025-04-07&analytic_id=NFV4-LPR2"
{  "ok": true,  "message": "success",  "data": {    "time_range": "daily",    "start_date": "2025-04-01",    "end_date": "2025-04-07",    "summary": {      "total": 750,      "known_plates": 500,      "unknown_plates": 250,      "known_percentage": 66.7,      "unknown_percentage": 33.3,      "vehicle_types": {        "car": 400,        "motorcycle": 250,        "truck": 100      },      "vehicle_type_percentage": {        "car": 53.3,        "motorcycle": 33.3,        "truck": 13.3      }    },    "time_series_data": [      {        "time_label": "2025-04-01",        "event_time": "2019-08-24T14:15:22Z",        "total": 120,        "known_plates": 80,        "unknown_plates": 40,        "vehicle_types": {          "car": 70,          "motorcycle": 40,          "truck": 10        },        "vehicle_type_percentage": {          "car": 58.3,          "motorcycle": 33.3,          "truck": 8.3        },        "percent_of_total": 16,        "change_from_previous": 8.5      }    ],    "stream_distribution": [      {        "stream_id": "stream-abc123",        "stream_name": "Lobby Utama",        "location": "Gedung A",        "percent_of_total": 38.5,        "total": 300,        "known_plates": 200,        "unknown_plates": 100      }    ],    "peak_time_info": {      "peak_time": "14:00",      "peak_count": 132,      "lowest_time": "03:00",      "lowest_count": 2    },    "trends": {      "overall_trend": "stable",      "average_per_interval": 107.1,      "peak_to_average_ratio": 1.7    },    "timestamp": "2019-08-24T14:15:22Z"  }}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}

Crowd Estimation

GET
/api/statistics/ce

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string

ID stream, pisahkan dengan koma untuk beberapa stream

start_date*string
Formatdate
end_date*string
Formatdate
instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/ce?stream_id=stream-plaza01&start_date=2025-04-01&end_date=2025-04-07"
{  "ok": true,  "message": "success",  "data": {    "time_range": "hourly",    "summary": {      "total_events": 2400,      "average_estimation": 45.2,      "peak_estimation": 120,      "lowest_estimation": 5,      "latest_estimation": 38,      "total_areas_monitored": 3    },    "time_series_data": [      {        "time_interval": "09:00",        "data": {          "total_events": 60,          "average_estimation": 50,          "peak_estimation": 80,          "lowest_estimation": 10,          "area_breakdown": [            {              "area": "Area A",              "average_estimation": 22.4,              "peak_estimation": 60,              "event_count": 800            }          ]        },        "percent_of_total": 2.5,        "change_from_previous": 10      }    ],    "stream_distribution": [      {        "stream_id": "stream-abc123",        "stream_name": "Lobby Utama",        "location": "Gedung A",        "percent_of_total": 38.5,        "total_events": 800,        "average_estimation": 42,        "peak_estimation": 110,        "areas": [          {            "area": "Area A",            "average_estimation": 20,            "peak_estimation": 55,            "latest_estimation": 18,            "event_count": 400          }        ]      }    ],    "area_distribution": [      {        "area": "Area A",        "total_events": 1200,        "average_estimation": 40,        "peak_estimation": 100,        "latest_estimation": 35,        "streams_count": 2,        "percent_of_total": 50      }    ],    "peak_time_info": {      "peak_period": "12:00",      "peak_estimation": 120,      "peak_location": "Gedung A",      "peak_area": "Area B",      "average_during_peak": 95,      "events_during_peak": 180    },    "trends": {      "overall_trend": "stable",      "trend_percentage": 2.5,      "busiest_periods": [        {          "period": "12:00-14:00",          "average_estimation": 90,          "description": "Jam makan siang"        }      ],      "quietest_periods": [        {          "period": "12:00-14:00",          "average_estimation": 90,          "description": "Jam makan siang"        }      ]    },    "timestamp": "2019-08-24T14:15:22Z"  }}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}

People Analytics (MPA)

GET
/api/statistics/mpa/counting

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string
start_date*string
Formatdate
end_date*string
Formatdate
instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/mpa/counting?stream_id=stream-entry01&start_date=2025-04-01&end_date=2025-04-07"
{  "ok": true,  "message": "success",  "data": {    "time_range": "hourly",    "summary": {      "in": 350,      "out": 310,      "total": 660,      "net_flow": 40,      "in_percentage": 53,      "out_percentage": 47    },    "time_series_data": [      {        "time_interval": "09:00",        "person": {          "in": 350,          "out": 310,          "total": 660,          "net_flow": 40,          "in_percentage": 53,          "out_percentage": 47        },        "percent_of_total": 8.3,        "change_from_previous": 5      }    ],    "stream_distribution": [      {        "stream_id": "stream-abc123",        "stream_name": "Lobby Utama",        "location": "Gedung A",        "percent_of_total": 38.5,        "total_count": 300,        "directional_data": {          "in": 350,          "out": 310,          "total": 660,          "net_flow": 40,          "in_percentage": 53,          "out_percentage": 47        },        "peak_time_interval": "12:00",        "peak_count": 45,        "busiest_periods": [          "12:00",          "17:00"        ]      }    ],    "peak_time_info": {      "peak_time_interval": "12:00",      "peak_traffic": {        "in": 350,        "out": 310,        "total": 660,        "net_flow": 40,        "in_percentage": 53,        "out_percentage": 47      },      "top_busy_periods": [        {          "time_interval": "string",          "count": 0        }      ],      "least_busy_periods": [        {          "time_interval": "string",          "count": 0        }      ]    },    "trends": {      "average_traffic_per_interval": 55,      "traffic_distribution": [        {          "time_period": "string",          "count": 0,          "percentage": 0        }      ],      "directional_trend": {        "dominant_direction": "in",        "directional_ratio": 1.13      }    },    "timestamp": "2019-08-24T14:15:22Z"  }}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
GET
/api/statistics/mpa/dwelling

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string
start_date*string
Formatdate
end_date*string
Formatdate
instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/mpa/dwelling?stream_id=stream-lobby01&start_date=2025-04-01&end_date=2025-04-07"
{  "ok": true,  "message": "success",  "data": {    "time_range": "hourly",    "summary": {      "count": 420,      "average_dwell_time": 185.5,      "min_dwell_time": 10,      "max_dwell_time": 900,      "median_dwell_time": 120,      "most_common_dwell_time": 60    },    "time_series_data": [      {        "time_interval": "09:00",        "count": 35,        "average_dwell_time": 200,        "median_dwell_time": 130,        "most_common_dwell_time": 60,        "min_dwell_time": 15,        "max_dwell_time": 750,        "change_from_previous": -5,        "area_data": {          "Area A": {            "count": 20,            "average_dwell_time": 180,            "median_dwell_time": 120,            "most_common_dwell_time": 60,            "min_dwell_time": 15,            "max_dwell_time": 750          }        }      }    ],    "stream_distribution": [      {        "stream_id": "stream-abc123",        "stream_name": "Lobby Utama",        "location": "Gedung A",        "percent_of_total": 38.5      }    ],    "peak_time_info": {      "peak_time_interval": "12:00",      "peak_count": 60,      "peak_average_dwell_time": 250,      "peak_median_dwell_time": 180,      "top_busy_periods": [        {}      ],      "least_busy_periods": [        {}      ]    },    "trends": {      "average_people_per_interval": 35,      "average_dwell_time": 185.5,      "min_dwell_time": 10,      "max_dwell_time": 900,      "median_dwell_time": 120,      "most_common_dwell_time": 60,      "occupancy_rate": 72.5,      "long_stay_frequency": 15.2    },    "timestamp": "2019-08-24T14:15:22Z"  }}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
GET
/api/statistics/mpa/density

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string
start_date*string
Formatdate
end_date*string
Formatdate
instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/mpa/density?stream_id=stream-hall01&start_date=2025-04-01&end_date=2025-04-01"
{  "ok": true,  "message": "success",  "data": {    "time_range": "hourly",    "start_date": "2025-04-01",    "end_date": "2025-04-01",    "summary": {      "count": 480,      "average_density": 4.2    },    "time_series_data": [      {        "time_interval": "09:00",        "count": 40,        "average_density": 4.5,        "area_data": {          "property1": {            "count": 0,            "average_density": 0          },          "property2": {            "count": 0,            "average_density": 0          }        },        "percent_of_total": 8.3,        "change_from_previous": 2      }    ],    "stream_distribution": [      {        "stream_id": "stream-abc123",        "stream_name": "Lobby Utama",        "location": "Gedung A",        "percent_of_total": 38.5      }    ],    "peak_time_info": {      "peak_time_interval": "12:00",      "peak_count": 72,      "peak_area": "Area B",      "peak_percentage": 45,      "off_peak_average": 3.2,      "peak_to_off_peak_ratio": 2.25    },    "trends": {      "low_density": 120,      "medium_density": 200,      "high_density": 160,      "low_density_percent": 25,      "medium_density_percent": 41.7,      "high_density_percent": 33.3    },    "timestamp": "2019-08-24T14:15:22Z"  }}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}

People Analytics Attributes (MPAA)

GET
/api/statistics/mpaa/counting

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string
start_date*string
Formatdate
end_date*string
Formatdate
instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/mpaa/counting?stream_id=stream-entrance01&start_date=2025-04-01&end_date=2025-04-07"
{  "ok": true,  "message": "success",  "data": {    "time_range": "hourly",    "summary": {      "total": 580,      "in": {        "count": 310,        "percentage": 53.4      },      "out": {        "count": 270,        "percentage": 46.6      },      "net_flow": 40,      "combined_attributes": {        "gender": {          "male": 320,          "female": 260        },        "age": {          "adult": 520,          "child": 60        },        "mask": {          "mask": 45,          "no_mask": 535        }      }    },    "time_series_data": [      {}    ],    "stream_distribution": [      {}    ],    "peak_time_info": {},    "trends": {},    "timestamp": "2019-08-24T14:15:22Z"  }}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
GET
/api/statistics/mpaa/dwelling

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string
start_date*string
Formatdate
end_date*string
Formatdate
instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/mpaa/dwelling?stream_id=stream-store01&start_date=2025-04-01&end_date=2025-04-07"
{  "ok": true,  "message": "success"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
GET
/api/statistics/mpaa/density

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string
start_date*string
Formatdate
end_date*string
Formatdate
instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/mpaa/density?stream_id=stream-concourse01&start_date=2025-04-01&end_date=2025-04-01"
{  "ok": true,  "message": "success"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}

Vehicle Analytics (MVA)

GET
/api/statistics/mva/counting

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string
start_date*string
Formatdate
end_date*string
Formatdate
instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/mva/counting?stream_id=stream-gate-main&start_date=2025-04-01&end_date=2025-04-07"
{  "message": "success",  "data": {    "time_range": "hourly",    "start_date": "2025-04-01",    "end_date": "2025-04-01",    "summary": {      "in": {        "count": 250,        "percentage": 52.1      },      "out": {        "count": 230,        "percentage": 47.9      },      "total": 480,      "net_flow": 20    },    "time_series_data": [      {        "time_interval": "09:00",        "vehicle": {          "in": {            "count": 0,            "percentage": 0          },          "out": {            "count": 0,            "percentage": 0          },          "total": 0,          "net_flow": 0,          "in_percentage": 0,          "out_percentage": 0        },        "percent_of_total": 8.3,        "change_from_previous": 3.5      }    ],    "stream_distribution": [      {        "stream_id": "stream-abc123",        "stream_name": "Lobby Utama",        "location": "Gedung A",        "percent_of_total": 38.5      }    ],    "peak_time_info": {      "peak_time_interval": "08:00",      "top_busy_periods": [        {          "time_interval": "string",          "count": 0        }      ],      "least_busy_periods": [        {          "time_interval": "string",          "count": 0        }      ]    },    "trends": {      "average_traffic_per_interval": 40,      "directional_trend": {        "net_flow_trend": "positive",        "dominant_direction": "in",        "directional_ratio": 1.09      }    },    "timestamp": "2019-08-24T14:15:22Z"  }}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
GET
/api/statistics/mva/dwelling

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string
start_date*string
Formatdate
end_date*string
Formatdate
instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/mva/dwelling?stream_id=stream-parking01&start_date=2025-04-01&end_date=2025-04-07"
{  "message": "success",  "data": {    "time_range": "hourly",    "start_date": "2025-04-01",    "end_date": "2025-04-01",    "summary": {      "count": 360,      "average_dwell_time": 240,      "min_dwell_time": 20,      "max_dwell_time": 1800,      "median_dwell_time": 180,      "most_common_dwell_time": 120    },    "time_series_data": [      {}    ],    "stream_distribution": [      {        "stream_id": "stream-abc123",        "stream_name": "Lobby Utama",        "location": "Gedung A",        "percent_of_total": 38.5      }    ],    "peak_time_info": {      "peak_time_interval": "10:00",      "peak_count": 55,      "peak_average_dwell_time": 320,      "top_busy_periods": [        {}      ],      "least_busy_periods": [        {}      ]    },    "trends": {      "average_vehicles_per_interval": 30,      "average_dwell_time": 240,      "occupancy_rate": 68,      "long_stay_frequency": 22.5    },    "timestamp": "2019-08-24T14:15:22Z"  }}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
GET
/api/statistics/mva/density

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string
start_date*string
Formatdate
end_date*string
Formatdate
instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/mva/density?stream_id=stream-road01&start_date=2025-04-01&end_date=2025-04-01"
{  "ok": true,  "message": "success",  "data": {    "time_range": "hourly",    "start_date": "2025-04-01",    "end_date": "2025-04-01",    "summary": {      "count": 520,      "vehicle_type_distribution": {        "car": 300,        "motorcycle": 150,        "truck": 70      }    },    "time_series": [      {}    ],    "stream_distribution": [      {        "stream_id": "stream-abc123",        "stream_name": "Lobby Utama",        "location": "Gedung A",        "percent_of_total": 38.5      }    ],    "peak_info": {      "peak_time_interval": "08:00",      "peak_count": 80,      "peak_area": "Gerbang Utama",      "peak_vehicle_type": "car"    },    "trends": {      "low_density": 80,      "medium_density": 180,      "high_density": 260,      "low_density_percent": 15.4,      "medium_density_percent": 34.6,      "high_density_percent": 50    },    "timestamp": "2019-08-24T14:15:22Z"  }}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
GET
/api/statistics/mva/speed

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string
start_date*string
Formatdate
end_date*string
Formatdate
instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/mva/speed?stream_id=stream-highway01&start_date=2025-04-01&end_date=2025-04-01"
{  "ok": true,  "message": "success",  "data": {    "time_range": "hourly",    "start_date": "2025-04-01",    "end_date": "2025-04-01",    "summary": {      "total_count": 540,      "avg_speed": 42.5,      "min_speed": 5,      "max_speed": 120,      "speed_distribution": {        "slow": {          "count": 80,          "label": "< 20 km/j",          "percentage": 14.8        },        "medium": {          "count": 200,          "label": "20-60 km/j",          "percentage": 37        },        "fast": {          "count": 180,          "label": "60-100 km/j",          "percentage": 33.3        },        "very_fast": {          "count": 80,          "label": "> 100 km/j",          "percentage": 14.8        }      }    },    "time_series_data": [      {        "time_interval": "09:00",        "count": 45,        "avg_speed": 44,        "min_speed": 8,        "max_speed": 105      }    ],    "stream_distribution": [      {        "stream_id": "stream-abc123",        "stream_name": "Lobby Utama",        "location": "Gedung A",        "percent_of_total": 38.5      }    ],    "peak_time_info": {      "peak_time_interval": "07:00",      "peak_count": 85,      "peak_avg_speed": 38.2,      "top_busy_periods": [        {}      ],      "least_busy_periods": [        {}      ]    },    "trends": {      "average_events_per_interval": 45,      "overall_avg_speed": 42.5    },    "timestamp": "2019-08-24T14:15:22Z"  }}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}

Vehicle Analytics Attributes (MVAA)

GET
/api/statistics/mvaa/counting

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string
start_date*string
Formatdate
end_date*string
Formatdate
instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/mvaa/counting?stream_id=stream-gate-vip&start_date=2025-04-01&end_date=2025-04-07"
{  "ok": true,  "message": "success"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
GET
/api/statistics/mvaa/dwelling

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string
start_date*string
Formatdate
end_date*string
Formatdate
instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/mvaa/dwelling?stream_id=stream-parking-vip&start_date=2025-04-01&end_date=2025-04-07"
{  "ok": true,  "message": "success"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
GET
/api/statistics/mvaa/density

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

stream_id*string
start_date*string
Formatdate
end_date*string
Formatdate
instance?string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/mvaa/density?stream_id=stream-road-attr01&start_date=2025-04-01&end_date=2025-04-01"
{  "ok": true,  "message": "success"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}

Ekspor PDF Legacy per Kategori

POST
/api/statistics/{category}/export

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

category*string

Kategori statistik yang akan diekspor

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

curl -X POST "https://lenz.example.com/api/statistics/fr/export" \  -H "Content-Type: application/json" \  -d '{    "format": "pdf",    "lang": "id",    "timezone": "Asia/Jakarta",    "start_date": "2025-04-01",    "end_date": "2025-04-30",    "stream_ids": [      "stream-abc123",      "stream-def456"    ]  }'
{  "job_id": "export-job-abc123",  "status": "pending",  "category": "fr",  "estimated_time_seconds": 10}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
GET
/api/statistics/{category}/export/status/{job_id}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

category*string
job_id*string

Response Body

application/json

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/fr/export/status/export-job-abc123"
{  "job_id": "export-job-abc123",  "status": "completed",  "progress": 100,  "file_ready": true,  "error_message": "string",  "created_at": "2019-08-24T14:15:22Z",  "completed_at": "2019-08-24T14:15:22Z"}
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}
GET
/api/statistics/{category}/export/download/{job_id}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

category*string
job_id*string

Response Body

application/pdf

application/json

application/json

curl -X GET "https://lenz.example.com/api/statistics/fr/export/download/export-job-abc123"
"string"
{  "ok": false,  "message": "invalid request"}
{  "ok": false,  "message": "invalid request"}

On this page