REST API
Admin API Reference
Create, list, inspect, and delete datasets. You can also manage their Dashboard cards and charts.
Authentication
Create an Admin API key in Settings → Admin. Admin API keys use the TypeID format and start with admin_. The key gives access to every dataset in your account, so keep it secret.
1Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdyAdmin API keys manage datasets, Dashboard cards, and charts. The dataset API key returned by this API is used with the separate logs API.
Dataset object
/api/admin/v1/datasetsList all datasets owned by the account. Newest datasets come first.
Example
1curl "https://z8log.com/api/admin/v1/datasets" \
2 -H "Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdy"1{
2 "datasets": [
3 {
4 "id": "a1b2c3d4e5f",
5 "userId": "user_123",
6 "title": "Production",
7 "createdAt": 1767436200000,
8 "updatedAt": 1767436200000
9 }
10 ]
11}Status codes
200The request succeeded.401The Admin API key is missing or invalid.500The server could not load the datasets./api/admin/v1/datasetsCreate a dataset and return its dataset API key.
Dataset limits are per account: Free 2, Basic 10, Pro 50. Existing datasets stay available after a downgrade, but creating more is blocked while the account is at or above its limit. Metrics use the owner’s searchable history: 3, 7, or 30 days.
JSON body
Example
1curl -X POST "https://z8log.com/api/admin/v1/datasets" \
2 -H "Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdy" \
3 -H "Content-Type: application/json" \
4 -d '{ "title": "Production" }'1{
2 "dataset": {
3 "id": "a1b2c3d4e5f",
4 "userId": "user_123",
5 "title": "Production",
6 "createdAt": 1767436200000,
7 "updatedAt": 1767436200000,
8 "apiKey": "dataset_01h45ytscbebc8jsnatf2t1wdx"
9 }
10}The response has status 201 Created. Store the returned apiKey in a secure place.
Status codes
201The dataset was created.400The JSON body or title is invalid.401The Admin API key is missing or invalid.409The account has reached its plan’s dataset limit. Delete a dataset or upgrade before creating another.500The server could not create the dataset./api/admin/v1/datasets/{datasetId}Get one dataset and its dataset API key.
Example
1curl "https://z8log.com/api/admin/v1/datasets/a1b2c3d4e5f" \
2 -H "Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdy"1{
2 "dataset": {
3 "id": "a1b2c3d4e5f",
4 "userId": "user_123",
5 "title": "Production",
6 "createdAt": 1767436200000,
7 "updatedAt": 1767436200000,
8 "apiKey": "dataset_01h45ytscbebc8jsnatf2t1wdx"
9 }
10}Status codes
200The request succeeded.401The Admin API key is missing or invalid.404The dataset does not exist in this account.500The server could not load the dataset.Inspect, preview, then save
With an Admin key, first read GET /api/admin/v1/datasets/{datasetId}. The owned dataset response includes dataset.apiKey. Use that dataset key for POST /api/logs/{datasetId}/query. Start with logs() samples, inspect fields and types, and preview a numeric formula. Use the Admin key for card and Chart PUT calls, then GET the saved result to verify.
The Query API needs no title, color, or slot. It uses the same language validation as saves. Sample checks apply only to generated AI drafts. There is no extra Admin query route.
Use start=now-5m, now-15m, or now-30m and end=now for relative reads. The server resolves all formulas against one clock. Responses include resolved timeframe and aggregate parts. Preserve each result with its formula, parts, and range. Chart points include clipped start/end bounds; use those bounds for details.
Manage a Dashboard
Every Dashboard and Charts endpoint requires a set query parameter, including writes and deletes. Set numbers start at 1. Free allows 1 set per page, Basic 2, and Pro 5. Admin also allows 5 sets per page. A missing or invalid set returns 400; a set above the current plan limit returns 403 with code: set_limit. Downgrades preserve higher sets but block access until the plan allows them again.
Each dataset has independent Dashboard and Chart sets. Every Dashboard set has 12 fixed slots. A card stores its title, tone, formula, and display format. The Dashboard timeframe is not stored in a card.
- Call
GET /api/admin/v1/datasets/{datasetId}/dashboard?set=1without a timeframe to inspect all slot configurations. - Choose a slot from 1 to 12. Call
PUT /api/admin/v1/datasets/{datasetId}/dashboard/cards/{slot}?set=1with the complete card configuration. PUT creates or replaces the slot. - Call the Dashboard GET endpoint with
startandendto verify the calculated values. - Call
DELETE /api/admin/v1/datasets/{datasetId}/dashboard/cards/{slot}?set=1to clear a slot.
Formulas are written in the formula language. To write formulas for JSON data fields, first inspect logs with the dataset API key returned by the Admin API. Use stable fields such as data.userId and data.event. Z8Log cannot infer what an active user means; the formula must define it from fields present in the logs.
/api/admin/v1/datasets/{datasetId}/dashboard?set={set}Get all 12 Dashboard slots. Add both start and end to calculate card values for a range of up to 30 days.
Query parameters
Response fields
A timeframe can be at most 30 days; end can be at most five minutes ahead of server time.
Example
1curl "https://z8log.com/api/admin/v1/datasets/a1b2c3d4e5f/dashboard?set=1" \
2 -H "Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdy"1{
2 "timeframe": null,
3 "cards": [
4 { "slot": 1, "config": {
5 "title": "Errors",
6 "tone": "red",
7 "formula": "count(level = ERROR)",
8 "format": "number"
9 }, "value": null, "parts": [] },
10 { "slot": 2, "config": null, "value": null, "parts": [] }
11 ]
12}The real response always has 12 slot objects. This example only shows the first two.
Values example
1curl "https://z8log.com/api/admin/v1/datasets/a1b2c3d4e5f/dashboard?set=1&start=2026-09-02T00%3A00%3A00.000Z&end=2026-09-02T10%3A15%3A00.000Z" \
2 -H "Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdy"1{
2 "timeframe": {
3 "start": "2026-09-02T00:00:00.000Z",
4 "end": "2026-09-02T10:15:00.000Z"
5 },
6 "cards": [
7 {
8 "slot": 1,
9 "config": {
10 "title": "Error rate",
11 "tone": "red",
12 "formula": "count(level = ERROR) / count() * 100",
13 "format": "percent"
14 },
15 "value": { "raw": 4.2, "formatted": "4.2%" },
16 "parts": [
17 { "formula": "count(level = ERROR)", "logsFormula": "logs(level = ERROR)", "field": null, "raw": 42 },
18 { "formula": "count()", "logsFormula": "logs()", "field": null, "raw": 1000 }
19 ]
20 }
21 ]
22}The real response also includes the other 11 slots.
Value object
When a formula divides by zero, or a stored formula can no longer be read, the value is undefined:
1{
2 "raw": null,
3 "formatted": "-"
4}200The request succeeded.400The timeframe is invalid or longer than 30 days. No timezone-change detection is used.401The Admin API key is missing or invalid.404The dataset does not exist in this account.500The server could not load the Dashboard./api/admin/v1/datasets/{datasetId}/dashboard/cards/{slot}?set={set}Create or replace one Dashboard card. Slot must be an integer from 1 to 12.
Example
1curl -X PUT "https://z8log.com/api/admin/v1/datasets/a1b2c3d4e5f/dashboard/cards/1?set=1" \
2 -H "Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdy" \
3 -H "Content-Type: application/json" \
4 -d '{ "title": "Errors", "tone": "red", "formula": "count(level = ERROR)", "format": "number"}'Request body
1{
2 "title": "Errors",
3 "tone": "red",
4 "formula": "count(level = ERROR)",
5 "format": "number"
6}red, orange, yellow, lime, green, teal, cyan, blue, indigo, purple, pink, or gray.number shows the value as it is. percent adds one decimal place and a percent sign; the formula itself must multiply by 100.The card object must contain exactly these four fields. Missing fields and unknown extra fields return 400. An invalid formula returns 400 with an error message that starts with Formula: and names the column of the problem.
Aggregates, filters, operators, and limits are described on the Formula Language page. All formulas use the timeframe supplied to the Dashboard GET request. Do not put a timeframe inside a card configuration.
Distinct count example
1{
2 "title": "Active users",
3 "tone": "blue",
4 "formula": "distinct(data.userId, data.event = \"app_used\")",
5 "format": "number"
6}Active users percentage
1{
2 "title": "Active user rate",
3 "tone": "blue",
4 "formula": "distinct(data.userId, data.event = \"app_used\") / distinct(data.userId) * 100",
5 "format": "percent"
6}This example divides users with an app_used event by all users seen in logs during the requested Dashboard timeframe. Division by zero gives an undefined value.
Response
1{
2 "success": true
3}The server only accepts this formula language. Raw SQL and invalid fields are rejected. Valid data.* paths absent from samples are accepted. Saved formulas must be numeric.
200The card was saved.400The slot or card configuration is invalid.401The Admin API key is missing or invalid.404The dataset does not exist in this account.500The server could not save the Dashboard card./api/admin/v1/datasets/{datasetId}/dashboard/cards/{slot}?set={set}Clear one Dashboard slot. Clearing an empty slot also succeeds.
1curl -X DELETE "https://z8log.com/api/admin/v1/datasets/a1b2c3d4e5f/dashboard/cards/1?set=1" \
2 -H "Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdy"200The slot is empty.400The slot is invalid.401The Admin API key is missing or invalid.404The dataset does not exist in this account.500The server could not clear the Dashboard card./api/admin/v1/datasets/{datasetId}/dashboard/cards/move?set={set}Move a Dashboard card to an empty slot, or swap two filled slots.
Example
1curl -X POST "https://z8log.com/api/admin/v1/datasets/a1b2c3d4e5f/dashboard/cards/move?set=1" \
2 -H "Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdy" \
3 -H "Content-Type: application/json" \
4 -d '{ "from": 1, "to": 4 }'Request body
A filled source moves to an empty target. Two filled slots are swapped. An empty source makes no change and still succeeds.
1{
2 "success": true
3}200The move or swap was accepted.400The request body or either slot is invalid.401The Admin API key is missing or invalid.404The dataset does not exist in this account.500The server could not move the Dashboard card.Manage Charts
Each Chart set has four chart slots. A chart stores its title, tone, formula, display format, and chart type. The timeframe and adaptive bucket size are not stored in the chart.
- Call
GET /api/admin/v1/datasets/{datasetId}/charts?set=1without a timeframe to inspect all four slot configurations. - Choose a slot from 1 to 4. Call
PUT /api/admin/v1/datasets/{datasetId}/charts/{slot}?set=1with the complete chart configuration. PUT creates or replaces the slot. - Call the Charts GET endpoint with
startandendto calculate the formula once for every adaptive time bucket. - Use the move endpoint to move or swap charts. Use DELETE to clear a slot.
Charts use the same formula language as Dashboard cards. The formula is evaluated separately for every time bucket.
/api/admin/v1/datasets/{datasetId}/charts?set={set}Get all four chart slots. Add both start and end to calculate a time series for each configured chart.
Query parameters
Response fields
A requested timeframe can be at most 30 days; end can be at most five minutes ahead of server time. The server first restricts the request to available history, chooses a clean interval targeting 30 intervals, then expands start backward and end forward to full clock-aligned intervals without changing the interval size. Already aligned bounds stay unchanged. Queries include logs in the expanded range, subject to the plan's history limits and server time. The current interval displays its full bounds and fills as logs arrive. Alignment can produce 31 columns. Within the plan's available history, the fixed ranges use 15m / 30s, 1h / 2m, 6h / 15m, 24h / 1h, 3d / 3h, 7d / 6h, and 30d / 1d.
Configuration example
1curl "https://z8log.com/api/admin/v1/datasets/a1b2c3d4e5f/charts?set=1" \
2 -H "Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdy"1{
2 "timeframe": null,
3 "bucketMs": null,
4 "charts": [
5 { "slot": 1, "config": {
6 "title": "Errors over time",
7 "tone": "red",
8 "formula": "count(level = ERROR)",
9 "format": "number",
10 "visualization": "line"
11 }, "points": [] },
12 { "slot": 2, "config": null, "points": [] }
13 ]
14}The real response always has four slot objects. This example only shows the first two.
Time-series example
1curl "https://z8log.com/api/admin/v1/datasets/a1b2c3d4e5f/charts?set=1&start=2026-09-02T00%3A00%3A00.000Z&end=2026-09-02T10%3A15%3A00.000Z" \
2 -H "Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdy"1{
2 "timeframe": {
3 "start": "2026-09-02T00:00:00.000Z",
4 "end": "2026-09-02T10:30:00.000Z"
5 },
6 "bucketMs": 1800000,
7 "charts": [
8 {
9 "slot": 1,
10 "config": {
11 "title": "Errors over time",
12 "tone": "red",
13 "formula": "count(level = ERROR)",
14 "format": "number",
15 "visualization": "line"
16 },
17 "points": [
18 { "at": "2026-09-02T00:00:00.000Z", "start": "2026-09-02T00:00:00.000Z", "end": "2026-09-02T00:30:00.000Z", "value": { "raw": 3, "formatted": "3" }, "parts": [{ "formula": "count(level = ERROR)", "logsFormula": "logs(level = ERROR)", "field": null, "raw": 3 }] },
19 { "at": "2026-09-02T00:30:00.000Z", "start": "2026-09-02T00:30:00.000Z", "end": "2026-09-02T01:00:00.000Z", "value": { "raw": 5, "formatted": "5" }, "parts": [{ "formula": "count(level = ERROR)", "logsFormula": "logs(level = ERROR)", "field": null, "raw": 5 }] }
20 ]
21 }
22 ]
23}The real response includes every bucket and all four slots. A missing count bucket returns zero. Division by zero returns an undefined value with raw: null and formatted: "-".
200The request succeeded.400The timeframe is invalid or longer than 30 days. No timezone-change detection is used.401The Admin API key is missing or invalid.404The dataset does not exist in this account.500The server could not load the charts./api/admin/v1/datasets/{datasetId}/charts/{slot}?set={set}Create or replace one chart. Slot must be an integer from 1 to 4.
Example
1curl -X PUT "https://z8log.com/api/admin/v1/datasets/a1b2c3d4e5f/charts/1?set=1" \
2 -H "Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdy" \
3 -H "Content-Type: application/json" \
4 -d '{ "title": "Errors over time", "tone": "red", "formula": "count(level = ERROR)", "format": "number", "visualization": "line"}'Request body
1{
2 "title": "Errors over time",
3 "tone": "red",
4 "formula": "count(level = ERROR)",
5 "format": "number",
6 "visualization": "line"
7}red, orange, yellow, lime, green, teal, cyan, blue, indigo, purple, pink, or gray.number or percent. Percent adds one decimal place and a percent sign; the formula itself must multiply by 100.bar or line.The chart object must contain exactly these five fields. Missing fields and unknown extra fields return 400. Do not put a timeframe or bucket size inside a chart configuration.
Response
1{
2 "success": true
3}200The chart was saved.400The slot or chart configuration is invalid.401The Admin API key is missing or invalid.404The dataset does not exist in this account.500The server could not save the chart./api/admin/v1/datasets/{datasetId}/charts/{slot}?set={set}Clear one chart slot. Clearing an empty slot also succeeds.
1curl -X DELETE "https://z8log.com/api/admin/v1/datasets/a1b2c3d4e5f/charts/1?set=1" \
2 -H "Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdy"200The slot is empty.400The slot is invalid.401The Admin API key is missing or invalid.404The dataset does not exist in this account.500The server could not clear the chart./api/admin/v1/datasets/{datasetId}/charts/move?set={set}Move a chart to an empty slot, or swap two filled slots.
Example
1curl -X POST "https://z8log.com/api/admin/v1/datasets/a1b2c3d4e5f/charts/move?set=1" \
2 -H "Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdy" \
3 -H "Content-Type: application/json" \
4 -d '{ "from": 1, "to": 4 }'Request body
A filled source moves to an empty target. Two filled slots are swapped. An empty source makes no change and still succeeds.
1{
2 "success": true
3}200The move or swap was accepted.400The request body or either slot is invalid.401The Admin API key is missing or invalid.404The dataset does not exist in this account.500The server could not move the chart./api/admin/v1/datasets/{datasetId}Permanently delete a dataset and all logs stored in it.
Example
1curl -X DELETE "https://z8log.com/api/admin/v1/datasets/a1b2c3d4e5f" \
2 -H "Authorization: Bearer admin_01h45ytscbebc8jsnatf2t1wdy"1{
2 "success": true
3}Status codes
200The dataset was deleted.401The Admin API key is missing or invalid.404The dataset does not exist in this account.500The server could not delete the dataset.Errors
Errors use a JSON object with one error field.
1{
2 "error": "Not authorized"
3}