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:

FieldRequiredDescription
datayesThe typed payload. Validated against the widget's type schema — see Widget Types.
as_ofnoISO 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 with as_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.