Type: reference · Imported reference (adopted from the clarity backend developer docs)
Creating/listing time-series collections and writing numeric and blob data. All routes require auth. Mutating routes are HA-leader-gated (503 on a secondary). See API conventions.
Timestamps are epoch milliseconds. Numeric values are stored at fixed 0.001 precision; null denotes a missing value.
/exactapi/collectionList all collections (walks the on-disk hierarchy). Returns an array of collection objects. Note the metadata appears both nested under metadata and flattened at the top level.
[
{
"organization": "org1", "site": "s1", "unit": "u1", "grid": "default_grid",
"metadata": {
"descriptions": ["Inlet temp", "Line pressure"],
"tags": ["temperature", "pressure"],
"id": "col_abc123", "interval_ms": 60000
},
"descriptions": ["Inlet temp", "Line pressure"],
"tags": ["temperature", "pressure"],
"id": "col_abc123", "interval_ms": 60000
}
]
/exactapi/collection/{id}One collection by id (same shape as above), or:
404 { "error": "collection_not_found" }500 { "error": "metadata_invalid" } / { "error": "metadata_missing_or_unreadable" }/exactapi/create_collectionCreate a collection.
| Field | Type | Required | Notes |
|---|---|---|---|
organization |
string | yes | |
site |
string | yes | |
unit |
string | yes | |
grid |
string | yes | |
interval_ms |
u64 | preferred | Sampling interval (must divide a day). |
interval |
u64 | deprecated | Seconds; used as interval*1000 only if interval_ms==0. |
tags |
string[] | yes | |
descriptions |
string[] | optional | If present, must be the same length as tags. |
{
"organization": "org1", "site": "s1", "unit": "u1", "grid": "default_grid",
"interval_ms": 60000,
"tags": ["temperature", "pressure"],
"descriptions": ["Inlet temp", "Line pressure"]
}
Response — 200 a JSON string, e.g. "✅ Collection created with interval_ms: 60000ms". Missing interval → 400 { "error": "Either interval_ms or interval must be provided" }. Other errors → 500 { "error": "<message>" }.
/exactapi/update_collectionMerge metadata fields into an existing collection.
{
"organization": "org1", "site": "s1", "unit": "u1", "grid": "default_grid",
"updates": { "descriptions": ["new desc"], "interval_ms": 30000 }
}
grid defaults to "default_grid". Response — 200 { "status": "ok", "message": "metadata updated" }.
There is also a filesystem-style
/exactapi/collectionsresource with its own CRUD — see Special Resources.
Writes accept two body formats via RawWriteBody. Scope (organization/site/unit/grid) is optional — if omitted, each tag's collection is resolved from its name.
tags = { tag: [[ts_ms, value|null], ...] }.data = array of { timestamps: u64[], tag_values: { tag: (f32|null)[] } } (value arrays positionally aligned to timestamps)./exactapi/writefsync-durable write. Always returns HTTP 200, even on error (status is in the string).
Tag-keyed request:
{
"organization": "org1", "site": "s1", "unit": "u1", "grid": "default_grid",
"tags": {
"temperature": [[1700000000000, 23.5], [1700000060000, 23.7]],
"pressure": [[1700000000000, 1.01], [1700000060000, null]]
}
}
Bulk request:
{
"data": [
{ "timestamps": [1700000000000, 1700000060000],
"tag_values": { "temperature": [23.5, 23.7], "pressure": [1.01, null] } }
]
}
Response (HTTP 200): "✅ Write successful" (may append " (skipped N unresolved tag(s): a, b)") or "❌ <error>".
/exactapi/write_fastMemory-mapped write, no fsync — for large batches. Same body as /write. Uses real status codes:
| Status | Body |
|---|---|
| 200 | "✅ Fast Write successful" (+ optional skip note) |
| 400 | "❌ <parse/scope error>" |
| 500 | "❌ <storage error>" |
| 507 | "❌ <disk full>" |
/exactapi/write_bufferedQueued write with background flush. Body RawBufferedBody supports three shapes:
Single point:
{ "organization":"org1","site":"s1","unit":"u1","grid":"default_grid",
"tag": "temperature", "timestamp": 1700000000000, "value": 23.5 }
Bulk (data is an array):
{ "data": [ { "timestamps": [1700000000000], "tag_values": { "temperature": [23.5] } } ] }
Batched (data is an object):
{ "organization":"org1","site":"s1","unit":"u1","grid":"default_grid",
"data": { "temperature": [[1700000000000, 23.5]], "pressure": [[1700000000000, 1.01]] } }
Response
| Status | Body |
|---|---|
| 200 | { "status": "queued", "message": "Write queued successfully" } (or "Bulk"/"Batch") |
| 200 | { "status": "error", "message": "Invalid request format" } (parse/scope errors return 200) |
| 503 | { "status": "error", "message": "Queue failed: <e>" } (backpressure) |
| 507 | { "status": "error", "message": "<disk full>" } |
/exactapi/write_tag_mappingResolve mapped-tag specs to ids, auto-create the collection, then write.
{
"organization":"org1","site":"s1","unit":"u1","grid":"g1","interval_ms":60000,
"tags": [
{ "metricName": "temperature", "data": [[1700000000, 23.5]] },
{ "metricName": "pressure", "data": [[1700000000, 1.01]] }
]
}
Response — { "status": "ok", "message": "Write successful" } or { "status": "error", "message": "<e>" }. See tag_mappings for how specs resolve.
/exactapi/blob_writeWrite non-numeric values for blob-typed tags. Scope optional (all four → explicit, else resolved). data is required and non-empty.
{
"organization":"org1","site":"s1","unit":"u1","grid":"g1",
"data": {
"alarm_text": [[1700000000000, "OVERTEMP FAULT"]],
"spectrum": [[1700000000000, [0.1, 0.3, 0.7]]]
}
}
Response
| Status | Body |
|---|---|
| 200 | { "status": "ok", "written": 2, "unresolved": [] } |
| 400 | { "status": "error", "message": "data must contain at least one tag" } / "Invalid request format: ..." / "no tag resolved a scope ..." ("unresolved":[...]) |
| 500 | { "status": "error", "message": "<storage error>" } |
| 507 | { "status": "error", "message": "<disk full>" } |
Reading blobs is covered in Queries → Blob reads.
/exactapi/shadow_writeAuth required; accepted on a secondary node. Body is the raw write payload; on a secondary it is buffered into the HA shadow cache, on the leader it is a no-op. Always { "status": "ok" }.
/exactapi/seal_nowForce cold-tier sealing of day files.
| Field | Type | Required |
|---|---|---|
organization,site,unit,grid |
string | optional (all four to scope to one collection) |
include_today |
bool | optional (default false) |
{ "organization":"org1","site":"s1","unit":"u1","grid":"g1", "include_today": true }
Response — { "sealed": 12, "elapsed_ms": 843 }.
/exactapi/write_buffer_statsBuffered-writer queue statistics (all integers):
{ "total_queued": 100000, "total_flushed": 99997, "pending": 3,
"queue_full_errors": 0, "flush_errors": 0, "throughput_dps": 99997 }
Adopted from clarity backend developer docs (
docs/developer/api/collections-writes.md), imported reference.
Primary handlers:clarity:backend/src-tauri/src/main.rs:3950(create_collection),:4078(write_fast),:4103(write_buffered),:4124(shadow_write),:4174(seal_now).
Last updated: 2026-07-16 from clarity@bff451d