HTTP API
Implementation reference: src/sydra/http.zig.
Authentication
If auth_token is set in sydradb.toml, all routes under /api/* require:
Authorization: Bearer <auth_token>
Implementation: handleRequest auth guard.
GET /metrics
Returns Prometheus text exposition.
Implementation: handleMetrics.
GET /status
Returns a lightweight JSON health snapshot with:
statuscas_modemetadata_read_modequery_compiler_modecompatibility_debt.legacy_segment_descriptorscompatibility_debt.legacy_wal_descriptorscompatibility_debt.loose_refs_presentruntime.queue_depthruntime.memtable_bytesruntime.flush_totalruntime.flush_points_totalruntime.flush_seconds_totalruntime.wal_append_totalruntime.wal_append_seconds_totalruntime.ingest_totalruntime.ingest_rejected_totalruntime.ingest_rejected_mem_limit_totalruntime.wal_bytes_totalruntime.wal_append_failed_totalruntime.memtable_append_failed_totalruntime.ingest_quarantined_totalruntime.ingest_quarantine_write_failed_totalruntime.cas_sync_totalruntime.cas_sync_failed_totalruntime.cas_sync_seconds_totalruntime.query_compile_attempts_totalruntime.query_compile_success_totalruntime.query_compile_fallback_totalruntime.query_compile_unsupported_totalruntime.query_compile_series_not_found_totalruntime.query_compile_ambiguous_selector_totalruntime.query_compile_shadow_mismatch_totalruntime.cas_shadow_mismatch_total
Example:
{
"status": "ok",
"cas_mode": "dual_write",
"metadata_read_mode": "primary",
"query_compiler_mode": "compiled",
"compatibility_debt": {
"legacy_segment_descriptors": 0,
"legacy_wal_descriptors": 0,
"loose_refs_present": 0
},
"runtime": {
"queue_depth": 0,
"memtable_bytes": 0,
"flush_total": 3,
"flush_points_total": 17,
"flush_seconds_total": 0.125,
"wal_append_total": 19,
"wal_append_seconds_total": 0.004,
"ingest_total": 42,
"ingest_rejected_total": 1,
"ingest_rejected_mem_limit_total": 1,
"wal_bytes_total": 2048,
"wal_append_failed_total": 0,
"memtable_append_failed_total": 0,
"ingest_quarantined_total": 0,
"ingest_quarantine_write_failed_total": 0,
"cas_sync_total": 3,
"cas_sync_failed_total": 0,
"cas_sync_seconds_total": 0.031,
"query_compile_attempts_total": 9,
"query_compile_success_total": 6,
"query_compile_fallback_total": 3,
"query_compile_unsupported_total": 2,
"query_compile_series_not_found_total": 1,
"query_compile_ambiguous_selector_total": 0,
"query_compile_shadow_mismatch_total": 0,
"cas_shadow_mismatch_total": 0
}
}
POST /api/v1/ingest
Consumes NDJSON (newline-delimited JSON). Each line is an object with:
- Preferred telemetry envelope:
metric(string, required)ts(integer, required)value(number, optional)fields(object, optional): numeric-only; each field fans out into a sibling metric named<metric>.<field>labels(object, optional)kind("gauge"or"counter", optional)unit(string, optional)description(string, optional)
series(string, required)ts(integer, required)value(number, optional)fields(object, optional): ifvalueis missing, the first numeric field is usedtags(object, optional)
Implementation: handleIngest.
Returns:
{"ingested":123}
Error cases:
- A line that exceeds the internal buffer fails the request with
413 Payload Too Large. - If ingest backpressure is hit, the request fails with a JSON error and
503 Service Unavailable. - Telemetry lines with non-numeric
fieldsfail with a JSON400error. - Conflicting metric descriptor metadata fails with a JSON
409error.
POST /api/v1/query/range
Requires Content-Length and a JSON body:
start(integer, required)end(integer, required)series_id(integer) ormetric(string) orseries(string)labels(object, optional; preferred exact selector formetric)tags(object, optional; legacy exact selector forseries)
Returns a JSON array:
[{"ts":1694300000,"value":24.2}]
Implementation: handleQuery (POST JSON).
GET /api/v1/query/range?...
Query parameters:
series_id=<u64>(preferred) orseries=<string>metric=<string>(preferred overseriesfor telemetry workflows)labels=<string>(optional canonical JSON object for exact telemetry selectors)tags=<string>(optional, defaults to{})start=<i64>(required)end=<i64>(required)
Returns the same JSON array as the POST form.
Implementation: handleQueryGet (GET query string).
POST /api/v1/query/find
Request JSON:
tags(object): exact-match tag constraints (string values)op(string, optional):"and"(default) or"or"
Response JSON: array of matching series_id values.
Implementation: handleFind.
POST /api/v1/metrics/find
Request JSON:
prefix(string, optional)labels(object, optional)limit(integer, optional)
Response JSON: array of metric descriptors with:
metrickindunit(optional)description(optional)series_countlabel_keysfirst_tslast_ts
POST /api/v1/series/find
Request JSON:
metric(string, required)labels(object, optional)op(string, optional):"and"(default) or"or"limit(integer, optional)
Response JSON: array of series descriptors with:
series_idmetriclabelsfirst_tslast_ts
POST /api/v1/labels/values
Request JSON:
key(string, required)metric(string, optional)prefix(string, optional)limit(integer, optional)
Response JSON:
{"values":["api","worker"]}
POST /api/v1/metrics/health
Request JSON:
prefix(string, optional)labels(object, optional)inactive_before_ts(integer, optional)limit(integer, optional)
Response JSON: array of per-metric health summaries with:
metrickindseries_countinactive_series_countinactivelabel_keysmissing_metadatafirst_tslast_ts
POST /api/v1/query/compare
Request JSON:
start(integer, required)end(integer, required)baseline_start(integer, required)baseline_end(integer, required)aggregate(string, required):last,avg,sum,min,max,count, ordeltaseries_id(integer) ormetric(string) orseries(string)labels(object, optional; preferred exact selector formetric)tags(object, optional; legacy exact selector forseries)
Response JSON:
series_idmetric(when known)labels(when known)aggregatemetric_kindcurrent:{start,end,samples,value}baseline:{start,end,samples,value}change_abschange_pct
POST /api/v1/annotations/write
Request JSON:
kind(string, required)title(string, required)message(string, optional)metric(string, optional)labels(object, optional)start(integer, required)end(integer, optional; defaults tostart)
Response JSON: the stored annotation record.
POST /api/v1/annotations/query
Request JSON:
start(integer, optional)end(integer, optional)kind(string, optional)metric(string, optional)labels(object, optional)op(string, optional):"and"(default) or"or"limit(integer, optional)
Response JSON: array of annotation records with:
idkindtitlemessage(optional)metric(optional)startendlabels
POST /api/v1/sydraql
Request body is plain text sydraQL.
Response JSON object:
columns: array of{name,type,nullable}rows: array of row arraysstats: execution timings and operator stats
When the query runs on the compiled path or falls back from it, stats also carries:
execution_modelegacy_fallbackfallback_reason(when a fallback occurred)selector_modeselected_series_count
Error responses for /api/* are JSON:
{"error":"query required","code":"query_required","status":400}
For sydraQL specifically, code now distinguishes:
parse_failed– lexer/parser failures such as unexpected tokens or malformed literalsvalidation_failed– syntactically valid queries that fail semantic validation- compiler/runtime contract reasons such as
unsupported_statement,unsupported_fill,unsupported_grouping,unsupported_projection,unsupported_ordering,unsupported_predicate,unsupported_expression,unsupported_function,series_not_found,ambiguous_selector, andshadow_mismatch shadow_mismatch– shadow-mode verification failuresquery_too_large– query text exceeds the current65536byte execution ceilingexecution_error– other runtime failures that do not fit the categories above
stats.fallback_reason uses a stable taxonomy for the current alpha subset:
unsupported_statementunsupported_fillunsupported_tag_filterunsupported_groupingunsupported_aggregateunsupported_projectionunsupported_orderingunsupported_predicateunsupported_expressionunsupported_functionseries_not_foundambiguous_selectorshadow_mismatch
Implementation:
Debug endpoints
GET /debug/compat/stats– JSON countersGET /debug/compat/catalog– JSON snapshot of compat catalog objectsGET /debug/alloc/stats– JSON allocator stats (only insmall_poolallocator mode)
See also:
SeriesIdderivation and caveats- Configuration (auth, ports, data dir)