SapixDB Wire Protocol
This document specifies the SapixDB wire protocol in sufficient detail for a third-party developer to implement a conforming client independently. It covers the transport layer, versioning, authentication, request and response formats, mandatory cryptographic fields, and error handling.
Protocol Overview
The SapixDB protocol is a JSON-over-HTTP application protocol. All communication between a client and a SapixDB agent uses standard HTTP/1.1 or HTTP/2 framing with JSON-encoded request and response bodies. The protocol is stateless at the HTTP level; persistent state is maintained within the agent's strand (the append-only hash-linked record chain).
The SapixDB protocol is not compatible with gRPC. A conforming SapixDB client cannot be an unmodified gRPC client for the following reasons, each of which creates an incompatibility at the wire level:
- Serialisation: SapixDB uses
Content-Type: application/json. gRPC uses binary Protocol Buffers withContent-Type: application/grpc. A gRPC client cannot parse SapixDB's JSON responses. - Path structure: gRPC mandates
/{package}.{Service}/{Method}. SapixDB uses resource-oriented paths such as/v1/agents/{id}/query. gRPC clients perform strict path validation and will reject SapixDB paths. - Mandatory cryptographic response fields: Every SapixDB record response includes
content_hashandparent_hashas BLAKE3 hash fields. A conforming client must validate these fields. No gRPC client produces or validates these fields. - Ed25519 record signatures: Every record carries an Ed25519 signature from the owning agent, included as a first-class field. This is a SapixDB protocol primitive with no gRPC equivalent.
Transport and TLS
2.1 TLS Requirements
All SapixDB connections must use TLS 1.3. Plaintext connections are rejected by default. Servers must not offer TLS versions below 1.2. The recommended configuration is TLS 1.3-only.
Server authentication via a valid TLS certificate is required. Clients must validate the server certificate chain and hostname. Self-signed certificates may be used in development but must not be accepted without explicit operator configuration.
2.2 HTTP Version
SapixDB agents accept HTTP/1.1 and HTTP/2. HTTP/2 is preferred for its multiplexing properties when a client issues concurrent queries. The server negotiates the HTTP version via ALPN during TLS handshake.
2.3 Default Port
The registered port for SapixDB client connections is 7475 (service name: sapixdb). All query, read, write, agent management, and semantic query operations are multiplexed on this single port. Administrative operations may be served on a separate operator-configured port (default: the dynamic range). Inter-agent mesh traffic may also be served on a separate operator-configured port.
Versioning
All SapixDB endpoints are versioned via the URL path prefix. The current stable version is v1, expressed as /v1/ at the start of every endpoint path.
When a new major version introduces breaking changes, it is served under a new path prefix (e.g. /v2/) while /v1/ continues to be served for a documented deprecation period. Clients must specify the version explicitly in every request path. A request to /records (without a version prefix) returns 404 Not Found.
Within a major version, new fields may be added to response objects and new endpoints may be added. Existing fields are never removed within a major version. Clients must treat unknown fields in responses as ignorable (forward-compatible parsing).
3.1 Version Header
Responses from a SapixDB agent include the following header identifying the agent's protocol version:
Clients may use this header to verify they are communicating with a compatible agent version. Future major versions will increment the major number.
Authentication
SapixDB supports three authentication mechanisms. The server advertises which mechanisms are accepted via theWWW-Authenticateheader on a 401 response. Anonymous access is disabled by default.
4.1 Bearer Token (JWT / API Key)
Clients pass a signed token or opaque API key in the HTTP Authorization header:
JWT tokens must be signed with Ed25519 (alg: EdDSA). The token payload must include sub (client identity),iat, and exp. Tokens with an expiry more than 24 hours in the future are rejected.
4.2 Mutual TLS (mTLS)
Clients may authenticate by presenting a client certificate during TLS handshake. The agent verifies the certificate against its configured trust store. mTLS is required for privileged administrative operations when the agent is configured to enforce administrator authentication.
4.3 API Key
Opaque API keys are accepted via the Bearer scheme. Keys are generated viaPOST /v1/auth/keysand stored as a BLAKE3 hash in the agent's policy store.
Request Format
All requests with a body must set Content-Type: application/json. Request bodies are UTF-8 encoded JSON objects. Maximum request body size is 64 MB (configurable). Requests that exceed the limit receive 413 Content Too Large.
GET requests do not have a body; parameters are passed as URL query string fields.
5.1 Required Headers
5.2 Idempotency Key
Write operations (POST to /v1/records) optionally accept an idempotency key. When present, a duplicate request with the same key within a 5-minute window returns the original response rather than creating a new record:
Response Format
All SapixDB responses use Content-Type: application/jsonand UTF-8 encoding. HTTP status codes follow standard semantics (2xx success, 4xx client error, 5xx server error).
6.1 Response Headers
X-SapixDB-Protocol-VersionstringREQUIRED1.0.X-SapixDB-Agent-IDstringREQUIREDX-SapixDB-Agent-Sigbase64url stringREQUIREDGET /v1/status). A conforming client must reject responses with invalid or missing signatures when signature verification is enabled.Cryptographic Primitives
Cryptographic integrity is a first-class primitive of the SapixDB protocol, not an optional extension. The following fields are present in every record returned by any endpoint and are mandatory for a conforming client to process:
7.1 Record Structure
Every record response object includes the following mandatory fields:
record_idstring (UUID v7)REQUIREDcontent_hashstring (BLAKE3, 64 hex chars)REQUIREDparent_hashstring (BLAKE3, 64 hex chars) | nullREQUIREDnull only for the genesis record (the first record in a strand). Forms the cryptographic chain: a conforming client can verify the entire strand by traversing parent_hash links from any record back to genesis, recomputing BLAKE3 at each step.timestamp_hlcuint64timestamp_hlc = (unix_ms << 16) | counter. Monotonically increasing across writes on the same agent. Upper 48 bits are wall-clock milliseconds; lower 16 bits are a counter for sub-millisecond ordering.timestamp_msuint64timestamp_hlc >> 16. Provided as a convenience field; clients should use timestamp_hlc for ordering when sub-millisecond precision is required.payload_b64string (base64-encoded MessagePack)content_hash was computed.payloadobject | nullpayload_b64 for cryptographic verification.flagsuint80 = normal record;1 = supersession (this record replaces a previous one);2 = tombstone (logical deletion).7.2 Ed25519 Agent Keypair
Each SapixDB agent holds a permanent Ed25519 keypair. The keypair is derived deterministically from a 32-byte seed (SAPIX_KEYPAIR_SEED_HEX). The private key never leaves the agent process.
The agent's Ed25519 public key is returned by GET /v1/statusin the public_key_hex field. A client that has cached this key can verify the X-SapixDB-Agent-Sig header on every response without trusting the transport layer alone.
7.3 Chain Verification
A conforming client can independently verify the integrity of any segment of a strand using the following algorithm:
The endpoint GET /v1/strand/verify performs this verification server-side across the entire strand and returns a summary. Clients may also perform this verification locally using the exported strand.
Core Endpoint Reference
All paths are relative to the agent base URL (e.g. https://agent.example.com:7475). All endpoints require authentication unless otherwise noted.
8.1 Health and Status
/v1/health is unauthenticated./v1/statusreturns agent metadata including the agent's Ed25519 public key (public_key_hex), record count, and protocol version.
8.2 Genesis
8.3 Records — Write
8.4 Records — Read
8.5 SaQL Queries (Tier 2 Structured)
8.6 Semantic Queries (Tier 1 Natural Language)
The source field indicates how the plan was produced: from the plan cache, the built-in heuristic planner, or an LLM. Theplan field is the compiled SaQL query object (same shape as Tier 2 query bodies) returned for client-side caching and transparency.
8.7 Multi-Agent Queries
8.8 Organisms (Named Agent Groups)
Error Responses
Error responses use standard HTTP status codes and return a JSON body with a single error field containing a human-readable message:
400Bad RequestMalformed JSON body or invalid field value.401UnauthorizedMissing or invalid authentication credentials.403ForbiddenAuthenticated but not authorised for this operation.404Not FoundAgent, record, or resource does not exist.409ConflictDuplicate genesis; idempotency key collision.413Content Too LargeRequest body exceeds the size limit.422Unprocessable EntitySemantic query could not be interpreted.500Internal Server ErrorAgent storage or runtime error.Port Usage
SapixDB is designed to operate all client traffic — reads, writes, queries, agent management, and semantic queries — over a single registered port (7475). This follows the RFC 7605 principle of in-band multiplexing as the preferred alternative to multiple registered ports.
10.1 Inter-agent Mesh Traffic
Replication and mesh synchronisation between SapixDB agent instances is deployment-internal traffic. It does not require a separately registered port. The inter-agent port is user-configurable via the SAPIX_MESH_PORT environment variable and defaults to a value in the dynamic range (49152–65535). Network operators should restrict this port to internal network segments.
10.2 Administrative Access
Administrative operations (key management, agent lifecycle, audit log access) are served over the primary port 7475 using a privileged authentication tier. Operators may optionally configure a separate admin port via SAPIX_ADMIN_PORT, which defaults to the dynamic range. The admin port uses the same wire protocol with mTLS required.