The numbers of a draft widget
const url = 'https://beta-api.plune.ai/v1/widgets/data';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"config":{"schemaVersion":1,"render":"line","bucket":"day","accumulated":false,"blocks":[{"entity":"run","metric":"count","filters":[{"property":"kind","values":["automated"]}]},{"entity":"run_result","metric":"count","filters":[{"property":"status","values":["failed","broken"]}]}],"segment":{"by":"label","values":["nightly"]}},"from":"2026-10-01T00:00:00Z","to":"2026-10-03T23:59:59Z","tz":"Europe/Kyiv"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://beta-api.plune.ai/v1/widgets/data \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "config": { "schemaVersion": 1, "render": "line", "bucket": "day", "accumulated": false, "blocks": [ { "entity": "run", "metric": "count", "filters": [ { "property": "kind", "values": [ "automated" ] } ] }, { "entity": "run_result", "metric": "count", "filters": [ { "property": "status", "values": [ "failed", "broken" ] } ] } ], "segment": { "by": "label", "values": [ "nightly" ] } }, "from": "2026-10-01T00:00:00Z", "to": "2026-10-03T23:59:59Z", "tz": "Europe/Kyiv" }'The numbers of a recipe that is not saved, so the builder can redraw as the person configures. Judged exactly as a saved widget: the closed catalogue, the caps, the cost guard BEFORE any query (400 widget_too_expensive), a denominator on every block. Nothing is stored. It is a POST because the recipe is the body.
Authorizations
Section titled “Authorizations ”Request Body required
Section titled “Request Body required ”object
The whole recipe of a widget; the server judges it on every write and every draft. Entities: case, run_result, run, requirement (a defect is not one yet). Properties come from a closed catalogue: a case has type, state, priority, suite, is_flaky, is_muted, tag; a result status, sub_status, source, muted, case_priority, environment, label; a run kind, environment, status_event, label; a requirement type, status, priority, category. A donut takes one block. A segment is cut across all blocks and only by a property they all have (label for runs and results; any groupable property for a single entity). Limits: 5 blocks, 10 segment values, 10 filters a block, 16 KiB.
object
Line only: the population at each moment. For run_result and run (they only arrive); a case, a requirement and a defect wait.
object
A duration only for run_result and run.
object
A groupable property of the entity. More than 20 groups: the rest is folded into «Other» with a true sum.
object
ISO 8601 with a time zone. Both bounds are required: a widget has no «all time».
The reader’s time zone, like Europe/Kyiv; the buckets are its calendar days, weeks (Monday) or months. Default UTC.
Example
{ "config": { "schemaVersion": 1, "render": "line", "bucket": "day", "accumulated": false, "blocks": [ { "entity": "run", "metric": "count", "filters": [ { "property": "kind", "values": [ "automated" ] } ] }, { "entity": "run_result", "metric": "count", "filters": [ { "property": "status", "values": [ "failed", "broken" ] } ] } ], "segment": { "by": "label", "values": [ "nightly" ] } }, "from": "2026-10-01T00:00:00Z", "to": "2026-10-03T23:59:59Z", "tz": "Europe/Kyiv"}Responses
Section titled “ Responses ”The numbers
The numbers of a widget. Every block shares one time axis; every block carries its denominator.
object
The start of each bucket, as a calendar date in the reader’s zone; at most 366.
At most 50 (blocks x groups x segment values), the biggest first when cut; empty for a table.
object
null: no value of the grouped property, or no Group by.
Over the whole period: what a donut slice or a table row shows.
object
A table’s rows, at most 500.
object
A6: per block, how many objects of the entity the project has in the period BEFORE the filters (denominator) and after them (matched). null for a block that ran out of time.
object
Series or rows were dropped to hold the caps.
What could not be measured or shown whole, as codes: truncated_series, truncated_rows, folded_groups, block_timeout.
object
object
Example
{ "render": "line", "bucket": "day", "from": "2026-10-01T00:00:00.000Z", "to": "2026-10-03T23:59:59.000Z", "axis": [ "2026-10-01", "2026-10-02", "2026-10-03" ], "series": [ { "block": 0, "entity": "run", "group": null, "segment": "nightly", "total": 2, "points": [ { "t": "2026-10-01", "v": 1 }, { "t": "2026-10-02", "v": 1 }, { "t": "2026-10-03", "v": 0 } ] }, { "block": 1, "entity": "run_result", "group": null, "segment": "nightly", "total": 3, "points": [ { "t": "2026-10-01", "v": 0 }, { "t": "2026-10-02", "v": 3 }, { "t": "2026-10-03", "v": 0 } ] } ], "denominators": [ { "block": 0, "entity": "run", "denominator": 5, "matched": 2 }, { "block": 1, "entity": "run_result", "denominator": 120, "matched": 3 } ], "truncated": false, "notMeasured": []}Invalid recipe or window, a window over 366 points, or over the cost budget (a code and its params say which)
object
Example generated
{ "error": "example"}No / invalid token or session
A read-only member
object
Example generated
{ "error": "example"}Rate-limited: the per-route throttle, or the per-minute request limit of the plan an API token counts by (#1442; the body names the plan, #2092). Retry-After carries the seconds until the window rolls over.
object
Example generated
{ "error": "example"}Headers
Section titled “Headers ”Seconds until the window rolls over