Authentication
Every request to /api/v1/ is authenticated with an API key and secret, sent as two headers:
api-key: <KEY>
api-secret: <SECRET>
There is no Authorization: Bearer header and no cookie or session auth on the API. A request
missing either header gets 401 UNAUTHORIZED.
Create a key
Go to Settings → API Keys → Create in your org. You choose a preset at creation time, and the secret is shown once — copy it then.
| Preset | Grants | Use for |
|---|---|---|
push_only | snapshot: read + create, widget: read | Push scripts. Start here. |
read_only | read on widget, snapshot, dashboard | Dashboards, exports, audits |
full_access | every action on every model | Admin tooling |
custom | whatever you check | Anything else |
A push script only needs to create snapshots, so push_only is the right default — it cannot delete
widgets, edit history, or touch dashboards.
Scopes
A key's permissions are a per-model, per-action map (read, create, edit, delete across
widget, snapshot, dashboard, tags). Each endpoint checks one model:action pair — e.g.
POST …/snapshots requires snapshot:create. A key without it gets 403 FORBIDDEN.
Example
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 '{ "data": { "value": 145000, "label": "MRR", "unit": "$" } }'
A key is scoped to a single org; you can only read and write that org's widgets and snapshots.
Expired keys (past expires_at) also return 401.
Next: push data with Snapshots, or see the error codes.