Reference

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.

auth
Authorization: Bearer qvr_xxxxxxxxxxxx

Files

Create & list

POST/api/files
write

Create a file of a configured type and populate its data in one call.

ParameterTypeNotes
typestring · requiredA file type from the workspace config (e.g. "score").
titlestringDefaults to an auto title if omitted.
dataobjectField 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).
forcebooleanSkip dedupe when the type de-duplicates on create.
request → response
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.

GET/api/files
read

List files, optionally filtered. Rows carry each type's summary fields by default; ?fields= overrides the projection.

ParameterTypeNotes
typestringFilter to one file type. Required when any filter/sort param below is used.
statusstring · repeatableFilter by status id(s): ?status=playing&status=ended
qstringTitle substring search.
limitnumberMax rows. Default 100, capped at 1000.
fieldscsvData 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.
response
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 } ] } ] }
GET/api/files (filtered query)
read

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.

ParameterTypeNotes
data.<field>string · repeatableEquality 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_gteISO or epoch-msOnly files updated at/after this instant: ?updatedAt_gte=2026-07-01T00:00:00Z (or 1782172800000).
updatedAt_lteISO or epoch-msOnly files updated at/before this instant.
sortkey:dirupdatedAt | createdAt | title, each :asc or :desc. Default updatedAt:desc. File columns only (no data-field sort).
offsetnumberSkip N rows (with limit = paging). Default 0.
request → response
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

GET/api/files/:id
read

Fetch one file with its full data and KPIs.

response
{ "ok": true, "file": {
  "id": "cmq…", "title": "Alice · 250", "type": "score", "status": "ended",
  "data": "{\"player\":\"Alice\",\"value\":250}",
  "kpis": [ … ] } }
POST/api/files/:id/data
write

Set one or more data fields (and optionally the title). Writes through the real KPI path, so metrics update immediately.

ParameterTypeNotes
fieldsobjectField id → new value. Batch-applied in one mutation.
fieldId + valuestring + anySingle-field alternative to fields: {"fieldId":"value","value":600}.
titlestringOptionally rename the file. fields and/or title required.
request → response
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”.

POST/api/files/:id/status
write

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.

request
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": [] }
DELETE/api/files/:id
write

Permanently delete a file.

request
curl -X DELETE https://quiveros.ai/api/files/$ID \
  -H "Authorization: Bearer $QUIVER_KEY"
# → { "ok": true }

Metrics

Read computed values

You declare metrics in config (count, sum, max, grouped breakdowns, derived). The engine computes them — you just read the value.
GET/api/metrics
read

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.

ParameterTypeNotes
idstringA metric id from config. Omit for the full snapshot. The window/filter params below apply to single-metric reads.
periodstringRequest-time window: lifetime · 2026 · q1-2026 · w22-2026 · d2026-07-02. Omit to keep the metric’s own default window.
from / toYYYY-MM-DDCustom date range (inclusive), instead of period.
dateYYYY-MM-DDOne-day convenience — expands to from=to=date. Handy for daily boards.
tzIANA zoneMakes day windows follow local midnight: ?tz=America/Los_Angeles.
limitnumberTop-N rows of a grouped metric (leaderboards). Capped at 1000; omit to use the metric’s configured limit.
data.<field>string · repeatableEquality filter on a data-field value, applied at request time: ?data.daily_date=2026-07-01. Repeat for AND. Field ids validated against config.
daily leaderboard — one metric, any day
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

Everything below is one GET — no fetch-everything-and-reduce client side.
GETDaily leaderboard by date
read

A grouped metric filtered to one day’s files by a date field.

request
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"
GETMy records
read

All of one player’s files, newest first, with the values inlined.

request
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"
GETPresence — who’s on right now
read

Files in a live status that were touched in the last two minutes (epoch-ms works too).

request
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"
GETPoint lookup by several fields
read

Repeat data.<field> to AND conditions — e.g. one player’s entry for one day.

request
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

GET/api/files/search
read

Free-text recall over titles and data-field values.

response
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" } ] }
GET/api/activity
read

Recent changes across the workspace (field, value, actor, time).

request
curl "https://quiveros.ai/api/activity?limit=20" -H "Authorization: Bearer $QUIVER_KEY"
GET/api/orient
read

A one-call bootstrap bundle — purpose, singletons, active files, per-type counts, recent activity. Built for agents starting cold.

request
curl "https://quiveros.ai/api/orient" -H "Authorization: Bearer $QUIVER_KEY"

Workspace

Inspect the workspace & its config

GET/api/workspace
read

Workspace metadata; ?include=config returns the full schema (types, fields, statuses, metrics, views).

ParameterTypeNotes
includestringconfig · apikeys · secrets · variables
response
curl "https://quiveros.ai/api/workspace" -H "Authorization: Bearer $QUIVER_KEY"
# → { "workspace": { "id": "…", "name": "Quiver Archer", "configId": "personal.leaderboard", "userCount": 1 } }