gRPC & HTTP API
Endpoints
| Endpoint | Serves |
|---|---|
table-rpc.uk-lon-1.dodil.io:443 | gRPC — the whole dodil.tables.v1 surface, TLS |
https://table.uk-lon-1.dodil.io/v1/databases/{db}/sql/execute | HTTP — one SQL statement, JSON in and out |
https://table.uk-lon-1.dodil.io/v1/databases/{db}/sql/query | HTTP — read-only twin of execute |
POST /v1/sql/execute + header x-db-id: {db} | Legacy HTTP form; still served, prefer the path form |
{db} is the bare bucket name. The gateway qualifies it to the tenant-scoped storage id from your credential; never build an org-prefixed name yourself.
Credentials ride as gRPC metadata or an HTTP header:
| Credential | gRPC metadata | HTTP header |
|---|---|---|
| API key | api-key: dk_<id>:<secret> | Authorization: Basic base64(dk_<id>:<secret>) |
| Service account | api-key: <client_id>:<client_secret> | Authorization: Basic base64(client_id:client_secret) |
| Bearer JWT | authorization: Bearer <jwt> | Authorization: Bearer <jwt> |
The RPC surface
| Group | RPCs | Page |
|---|---|---|
| SQL | Execute | Execute |
| Reads | Query · QueryStream · GetRow · BatchGetRows · InferParams | Reads |
| Writes | Upsert · Delete · WriteStream · Commit | Writes |
| Tables | CreateTable · AlterTable · DropTable | Tables & maintenance |
| Maintenance | OptimizeTable · VacuumTable · Compact | Tables & maintenance |
| Database catalog | CreateDatabase · DropDatabase · ListDatabases · DescribeDatabase · GetDatabaseStats · UpdateDatabaseS3Credentials | Tables & maintenance |
| Control-plane authored | SetReservation · DeleteReservation · ReleaseDatabase · AdoptDatabase | Not tenant-callable — see Capacity |
Sibling services in the same package: TablesResidency (Load / Release / GetLoadState), TablesObserve (NodeStatus / Capacity / Health), TablesVector and TablesGraph — see Vector and Graph.
There is no Insert, Merge, Update, DeleteRows, ListTables, GetTable, DescribeTable, History or Restore RPC. Those are SQL statements through Execute; the dodil data table commands with those names build the statement for you. Templates for pipeline-bound tables are a control-plane call — Templates.
Wire conventions
| gRPC | HTTP | |
|---|---|---|
| Address | db_id request field | {db} path segment |
| Request | proto field names | { "sql": "…" } |
| Rows | RowSet — TypedRows (default) or an Arrow IPC stream | JSON objects keyed by column name |
int64 | native int64_value | JSON number; pass values beyond ±2⁵³−1 as strings |
NUMERIC / TIMESTAMP / DATE / UUID | canonical strings inside TypedRows | strings |
TypedRows column type codes follow the storage vocabulary: INT16, INT32 and INT64 for short, int and long, UUID for uuid, NUMERIC, TIMESTAMP, DATE, JSON, BYTES, BOOL, FLOAT32, FLOAT64, STRING, plus array, struct and vector. The full list with pg wire OIDs is on Data types.
Arrow input is validated before use: size caps are enforced first, the decoded schema must match the table’s declared schema, and dictionary-encoded or compressed IPC is rejected.
ExecuteResponse is a oneof: rows for SELECT / SHOW / DESCRIBE / EXPLAIN, rows_affected for DML, ddl for DDL — plus statement_kind, served_by, warnings and max_wal_ulid. Over HTTP that flattens to {"kind":"query"|"write"|"ddl", …}.
Read-your-writes across calls
On the Postgres wire the adapter carries this for you. Over gRPC and HTTP every request is independent, so the watermark is the session:
- Every write returns a ULID —
WriteAck.wal_ulid,WriteStreamAck.max_ulid,CommitResponse.max_wal_ulidorExecuteResponse.max_wal_ulid. - Pass it as
min_ulidon the nextQuery,GetRoworExecute. - That read observes at least that write, or fails rather than answering from a stale view.
You rarely need it within one process: reads default to the strongest consistency the plane can prove, and a read issued after a write’s acknowledgement sees it. The watermark matters when a different process must see a write it did not make. The HTTP door takes only {"sql": …} — no min_ulid, no parameters; use gRPC or the Postgres wire for those.
Next: Execute for the SQL entry point, or Reads and Writes for the typed RPCs.