Snapshots
Snapshots are how data gets into Snapshots. You don't query — you push a full, typed payload to a widget, and each push is stored as a new immutable version. Nothing is ever overwritten.
Push a snapshot
POST /api/v1/widgets/{widget_id}/snapshots
Requires snapshot:create. Body:
| Field | Required | Description |
|---|---|---|
data | yes | The typed payload. Validated against the widget's type schema — see Widget Types. |
as_of | no | ISO 8601 timestamp for the business time the data describes. Defaults to now. |
curl -X POST https://snapshots.finopsbricks.com/api/v1/widgets/WIDGET_ID/snapshots \
-H "api-key: <KEY>" -H "api-secret: <SECRET>" \
-H "Content-Type: application/json" \
-d '{
"as_of": "2026-01-31T00:00:00Z",
"data": { "value": 145000, "label": "MRR", "unit": "$", "delta": 12000 }
}'
On success you get 201 and the stored snapshot:
{
"data": {
"id": "sn_...",
"widget": "WIDGET_ID",
"version": 7,
"as_of": "2026-01-31T00:00:00.000Z",
"received_at": "2026-02-01T09:14:22.017Z",
"data": { "value": 145000, "label": "MRR", "unit": "$", "delta": 12000 }
}
}
If data fails schema validation you get 422 VALIDATION_ERROR with a details array naming each
problem. See Error Codes.
as_of vs received_at
Two timestamps, two axes:
as_of— the business time the data is about. You set it. It drives the dashboard's freshness stamp. Push January's numbers on Feb 1 and backdate them withas_of.received_at— wall-clock time the push landed. The server sets it. It drives the audit trail (when did this restatement actually arrive?).
A late-arriving correction has an old as_of but a new received_at — that gap is the point.
Versioning
Each push increments version (max + 1 for the widget), starting at 1. Versions are immutable —
there is no update or overwrite. The dashboard renders the latest version and lets you scrub back
through prior ones to see how the picture changed over time (restatement auditing).
A UNIQUE(widget, version) constraint guards concurrent double-pushes: if two pushes race for the
same version number, one wins and the other errors rather than silently duplicating.
Read history
GET /api/v1/widgets/{widget_id}/snapshots
Requires snapshot:read. Returns versions newest-first — the scrubber's data source. Paginated;
see Pagination.
curl https://snapshots.finopsbricks.com/api/v1/widgets/WIDGET_ID/snapshots \
-H "api-key: <KEY>" -H "api-secret: <SECRET>"
Both endpoints return 404 if the widget doesn't exist in your org.