quverOS
DocsReference
REST API
Plain HTTP over https://quiveros.ai/api/*. Authenticate every request with a qvr_ workspace key. Reads are GET; writes are POST/PATCH/DELETE and need a write-capable key.
Authorization: Bearer qvr_xxxxxxxxxxxx
Files
Create & list
Create a file of a configured type and populate its data in one call.
| Parameter | Type | Notes |
|---|---|---|
| type | string · required | A file type from the workspace config (e.g. "score"). |
| title | string | Defaults to an auto title if omitted. |
| data | object | Field id → value. Use an array for multi-value fields. |
| parent | { id, field } | Append the new file to a parent file’s list field (a sub-item). |
| status | string | Create directly in this status of the type’s workflow (recorded like a status move). An unknown id returns 422 listing the valid ones. |
| force | boolean | Skip dedupe when the type de-duplicates on create. |
| idempotency_key | string | Or the Idempotency-Key header (1-200 printable characters). A repeat with the same key in the same workspace returns the ORIGINAL file with replayed: true instead of creating another — so a create whose response was lost can be retried safely. |
curl -X POST https://quiveros.ai/api/files \
-H "Authorization: Bearer $QUIVER_KEY" -H "content-type: application/json" \
-d '{"type":"score","title":"Alice · 250","data":{"player":"Alice","value":250}}'
{ "ok": true, "file": { "id": "cmq…", "type": "score", "title": "Alice · 250" } }Types that de-duplicate on create won’t spawn a near-duplicate: a confident match returns the existing file with reused: true (your fields merged in — empty fields filled, lists unioned, conflicts reported); several plausible matches return 409 with candidates. Pass force: true to create anyway.
A create is atomic: the file, its fields, its status and the parent link land together or not at all. If a step fails, what was written is rolled back and the response (500) says which step failed and that nothing was saved, with rolled_back: true and retryable: true.
Create many files in one request: up to 200 items, each exactly like a POST /api/files body, applied in order.
| Parameter | Type | Notes |
|---|---|---|
| items | array · required | Create bodies (type, title, data, parent, status, force, idempotency_key). At most 200 (413 above). |
| atomic | boolean | All or nothing: the first failure rolls back every file this request created and skips the rest. Default: every item is attempted and reported. |
curl -X POST https://quiveros.ai/api/files/batch \
-H "Authorization: Bearer $QUIVER_KEY" -H "content-type: application/json" \
-d '{"items":[{"type":"task","title":"A","parent":{"id":"$P","field":"tasks"},"idempotency_key":"run1:0"},
{"type":"task","title":"B","status":"nope"}]}'
{ "ok": false, "atomic": false, "created": 1, "failed": 1, "results": [
{ "index": 0, "ok": true, "status": 200, "file": { "id": "cmq…", "type": "task", "title": "A" } },
{ "index": 1, "ok": false, "status": 422, "error": "Unknown status 'nope' for type 'task'. Valid statuses: …" } ] }List files, optionally filtered. Rows carry each type's summary fields by default; ?fields= overrides the projection.
| Parameter | Type | Notes |
|---|---|---|
| type | string | Filter to one file type. Required when any filter/sort param below is used. |
| status | string · repeatable | Filter by status id(s): ?status=playing&status=ended |
| q | string | Title substring search. |
| limit | number | Max rows. Default 100, capped at 1000. |
| parent | file id | Only the files linked under this parent through its list link fields, in link order (response gains total and parent). Must be visible to you; children you can’t see are omitted. Composes with type, status, q, limit, offset, fields. |
| parent_field | field id | With parent: only this link field. |
| fields | csv | Data fields to include as KPIs: ?fields=value,category. OMITTED: each row carries its type’s summary_fields (what its list views show; a type without summary_fields falls back to its first three data fields). EMPTY (?fields=): status-only rows. Rows never include non-requested fields — fetch a file’s /kpis for everything. |
curl "https://quiveros.ai/api/files?type=score&fields=player,value&limit=50" \
-H "Authorization: Bearer $QUIVER_KEY"
{ "files": [
{ "id": "cmq…", "title": "Alice · 250", "type": "score", "status": "ended",
"kpis": [
{ "pathKey": "status", "stringValue": "ended" },
{ "pathKey": "dataFields.player", "stringValue": "Alice" },
{ "pathKey": "dataFields.value", "numericValue": 250 } ] } ] }Adding any of the params below switches the list into a real query: filter by data-field value, by last-update time, sort, and page. Requires type; the response gains a total count for paging. The other list params (status, q, fields, limit) still apply.
| Parameter | Type | Notes |
|---|---|---|
| data.<field> | string · repeatable | Equality match on a data-field value: ?data.player=Alice. Repeat for AND: &data.daily_date=2026-07-01. Field ids are validated against the type’s config. |
| updatedAt_gte | ISO or epoch-ms | Only files updated at/after this instant: ?updatedAt_gte=2026-07-01T00:00:00Z (or 1782172800000). |
| updatedAt_lte | ISO or epoch-ms | Only files updated at/before this instant. |
| sort | key:dir | updatedAt | createdAt | title, each :asc or :desc. Default updatedAt:desc. File columns only (no data-field sort). |
| offset | number | Skip N rows (with limit = paging). Default 0. |
curl "https://quiveros.ai/api/files?type=score&data.player=Alice&sort=updatedAt:desc&limit=20&offset=0" \
-H "Authorization: Bearer $QUIVER_KEY"
{ "files": [ { "id": "cmq…", "title": "Alice · 250", … } ], "total": 34 }Files
Read, update & delete a file
Fetch one file with its full data and KPIs.
{ "ok": true, "file": {
"id": "cmq…", "title": "Alice · 250", "type": "score", "status": "ended",
"data": "{\"player\":\"Alice\",\"value\":250}",
"kpis": [ … ] } }Set one or more data fields (and optionally the title). Writes through the real KPI path, so metrics update immediately.
| Parameter | Type | Notes |
|---|---|---|
| fields | object | Field id → new value. Batch-applied in one mutation. |
| fieldId + value | string + any | Single-field alternative to fields: {"fieldId":"value","value":600}. |
| title | string | Optionally rename the file. |
| add / remove | { field: value | [values] } | Add or remove single elements of multi-valued fields (incl. file links), against the current list — concurrent adds all land. Link targets must be files you can see. Removing a link never deletes the linked file, even from a field that owns its children (the response notes it). One of fields, title, add, remove is required. |
curl -X POST https://quiveros.ai/api/files/$ID/data \
-H "Authorization: Bearer $QUIVER_KEY" -H "content-type: application/json" \
-d '{"fields":{"value":600,"category":"hard"},"title":"Alice · 600"}'
{ "ok": true, "fields": { "value": 600, "category": "hard" }, "title": "Alice · 600",
"sideEffects": [ { "fieldId": "score_delta", "name": "Score Δ", "value": 350 } ] }Writes are CRDT-safe: they merge with concurrent live edits instead of clobbering them, and metrics update immediately. Unknown/uneditable fields come back in skipped; computed fields the write rippled into come back in sideEffects. If nothing changes, the call is a no-op and returns 400 “No fields applied”.
Move a file to a status in its workflow (e.g. playing → ended). PATCH works too; body can be JSON ({status}) or form-encoded (status=…). An id that isn’t in the type’s workflow returns 422.
curl -X POST https://quiveros.ai/api/files/$ID/status \
-H "Authorization: Bearer $QUIVER_KEY" -H "content-type: application/json" \
-d '{"status":"ended"}'
{ "ok": true, "fileId": "cmq…", "status": "ended", "sideEffects": [] }Permanently delete a file.
curl -X DELETE https://quiveros.ai/api/files/$ID \
-H "Authorization: Bearer $QUIVER_KEY"
# → { "ok": true }Metrics
Read computed values
With ?id= returns one metric (including its grouped breakdown); without, returns a snapshot of all metrics + a catalog. Key-only: this endpoint authenticates by qvr_ bearer key, never a session cookie.
| Parameter | Type | Notes |
|---|---|---|
| id | string | A metric id from config. Omit for the full snapshot. The window/filter params below apply to single-metric reads. |
| period | string | Request-time window: lifetime · 2026 · q1-2026 · w22-2026 · d2026-07-02. Omit to keep the metric’s own default window. |
| from / to | YYYY-MM-DD | Custom date range (inclusive), instead of period. |
| date | YYYY-MM-DD | One-day convenience — expands to from=to=date. Handy for daily boards. |
| tz | IANA zone | Makes day windows follow local midnight: ?tz=America/Los_Angeles. |
| limit | number | Top-N rows of a grouped metric (leaderboards). Capped at 1000; omit to use the metric’s configured limit. |
| data.<field> | string · repeatable | Equality filter on a data-field value, applied at request time: ?data.daily_date=2026-07-01. Repeat for AND. Field ids validated against config. |
curl "https://quiveros.ai/api/metrics?id=top_players_daily&period=lifetime&data.daily_date=2026-07-01" \
-H "Authorization: Bearer $QUIVER_KEY"
{ "metric": {
"id": "top_players_daily", "metric": 250,
"breakdown": [
{ "key": "Alice", "value": 250 },
{ "key": "Bob", "value": 175 } ] } }One configured metric serves every slice: the window params re-scope it per request (no per-day or per-week metric definitions), and data.<field> filters do a plain value match — so a daily board keyed by a date field avoids time-zone drift entirely.
Recipes
Common queries
A grouped metric filtered to one day’s files by a date field.
curl "https://quiveros.ai/api/metrics?id=top_players_daily&period=lifetime&data.daily_date=2026-07-01&limit=10" \ -H "Authorization: Bearer $QUIVER_KEY"
All of one player’s files, newest first, with the values inlined.
curl "https://quiveros.ai/api/files?type=score&data.player=Alice&sort=createdAt:desc&fields=value,daily_date&limit=25" \ -H "Authorization: Bearer $QUIVER_KEY"
Files in a live status that were touched in the last two minutes (epoch-ms works too).
NOW=$(($(date +%s) * 1000)); SINCE=$((NOW - 120000)) curl "https://quiveros.ai/api/files?type=score&status=playing&updatedAt_gte=$SINCE" \ -H "Authorization: Bearer $QUIVER_KEY"
Repeat data.<field> to AND conditions — e.g. one player’s entry for one day.
curl "https://quiveros.ai/api/files?type=score&data.player=Alice&data.daily_date=2026-07-01&fields=value" \ -H "Authorization: Bearer $QUIVER_KEY"
Discovery
Search, activity & orientation
Free-text recall over titles and data-field values.
curl "https://quiveros.ai/api/files/search?q=Alice&type=score&limit=5" \
-H "Authorization: Bearer $QUIVER_KEY"
# → { "results": [ { "id": "…", "title": "Alice · 250", "type": "score", "status": "ended" } ] }Recent changes across the workspace (field, value, actor, time).
curl "https://quiveros.ai/api/activity?limit=20" -H "Authorization: Bearer $QUIVER_KEY"
A one-call bootstrap bundle — purpose, singletons, active files (children rolled up under their active parent: status counts plus the open ones with their summary fields; a file linked from an active parent is listed there instead of again at the top level — active_linked says which), per-type counts, recent activity. Built for agents starting cold.
curl "https://quiveros.ai/api/orient" -H "Authorization: Bearer $QUIVER_KEY"
Workspace
Inspect the workspace & its config
Workspace metadata; ?include=config returns the full schema (types, fields, statuses, metrics, views).
| Parameter | Type | Notes |
|---|---|---|
| include | string | config · apikeys · secrets · variables |
curl "https://quiveros.ai/api/workspace" -H "Authorization: Bearer $QUIVER_KEY"
# → { "workspace": { "id": "…", "name": "Quiver Archer", "configId": "personal.leaderboard", "userCount": 1 } }