Name
groundhog-http: v1 client API over a Unix domain socket.
Transport
The service speaks HTTP/1.1 over the Unix socket configured by[server].socket. It does not
listen on TCP.
HTTP/1.1 requires a Host header, but Groundhog ignores its value. With curl:
Content-Type: application/json or a missing content type. The optional charset=utf-8 parameter is accepted.
Other media types, parameters, or any Content-Encoding return 415 before the body is read.
Authentication
If[server].token is non-empty, every request must include:
Current routes
An unknown path returns 404. A known path with another method returns 405 and an
Allow header.
HEAD returns the same status and headers as GET with no body.
Error documents
Most errors use:POST /v1/events
Appends one atomic batch:
v defaults to 1 when omitted. source and batch_id are batch-level fields. A submitted event
has exactly stream, record_key, kind, optional occurred_at, and payload.
The batch is rejected whole if any event is invalid. Empty batches are invalid. Limits are
10,000 events and 32 MiB of encoded body.
Idempotency
(source, batch_id) is reserved for the lifetime of the data directory. Groundhog computes a
canonical digest from the submitted content before assigning server fields.
A new batch returns:
status: "duplicate" and writes nothing.
Reusing the key for different content returns 409 and writes nothing.
A successful ingest receipt means the batch is durable. A lost response leaves the client
uncertain; retrying identical content under the same key safely converges on one batch.
Naming and bounds
source,stream, and ordinary name-like values are bounded and source/stream names match[a-z0-9_][a-z0-9_.-]*;record_keyandbatch_idmust be non-empty;- source
systemis reserved; - submitted batch IDs beginning with
groundhog/are reserved; and occurred_at, when supplied, is UTC with aZsuffix.
GET /v1/events
Replays authoritative history in increasing event_id order:
after is exclusive. limit must be a positive
integer no greater than [replay].max_limit; omission uses [replay].default_limit.
Response:
last_event_id is the last matching event returned and is omitted on an empty match. It is not
the progress cursor for a filtered subscription.
next_after is the position through which the request actually scanned. When the snapshot is
exhausted it advances to the snapshot frontier even if no event matched. Persist it for the next
poll so unrelated history cannot stall a filtered consumer.
snapshot_through_event_id is the coherent frontier captured for this request, or null for an
empty log.
POST /v1/query
Executes one confined read-only statement against one pinned published warehouse generation:
sql is required. format defaults to json, the available result format. limit and
timeout_secs default to configuration and must be positive and within their configured maxima.
Success:
SELECT or WITH statement over published relations. It rejects
mutations, multiple statements, file/network table functions, extension installation/loading,
attach/copy/import/export, secrets, shell access, mutating pragmas/settings, volatile functions,
and unproved order-dependent constructs.
A result cut by the server row limit requires a total top-level ORDER BY. The order must cover
all output columns; ORDER BY ALL is the simplest general form. Nested
LIMIT or OFFSET blocks require the same proof. Without a total order, an over-limit result is
rejected instead of returning an arbitrary subset.
Queries execute only against the last published generation. Events appended after its receipt
remain available through replay but are absent from SQL until project or rebuild publishes a
new frontier.
GET /v1/catalog
Returns published stream-level metadata:
Common status codes
A 429 rejected before mutation enqueue has written nothing and is retryable. Once mutation work
is enqueued, it is not abandoned because the client disconnects. A 503 means the writer cannot
accept further mutation until the service is closed and reopened through recovery.
Unavailable forms
The binary does not implement NDJSON streaming ingest,POST /v1/imports, observation ingest, or Arrow
query results. Sending their media types, routes, or formats does not activate partial behavior.
See also
serve,
configuration,
events,
warehouse,
getting started