- Your team — “save these leads”, “track this pipeline” — edited through this API or the web-UI grid. Tables created here are workspace-owned.
- Your agents — a durable relational scratchpad they read and write through the
hq:tablesMCP server. Agents can own their own tables and even evolve schema under governance.
https://api.hq.zone/v1/api/tables and authenticate with a personal access token: Authorization: Bearer hq_pat_.... Reads need the tables:read scope; writes need tables:write.
The tables subsystem is provisioned per deployment. If it isn’t configured for your workspace, these routes return
503 — enable the hq:tables integration (it ships opt-in/off) and ensure your workspace has the tables data plane provisioned.Field types
Each field has a logical type that maps to real typed storage. Pass the type as thetype string when you create a table or add a field:
formula, rollup, and lookup (computed fields) are a planned fast-follow, not yet available.required, is_unique, and indexed booleans (all default false), plus a free-form options object the surfaces interpret per type (for example, a link_to_record field records its target_table there).
Create a table
POST /v1/api/tables creates a workspace-owned table with its fields in one call.
1
Define the fields
Each field is
{ "name", "type", ... }. Optional per-field flags: required, is_unique, indexed, options, and link_target (for link_to_record).2
POST the table
The body takes Field names are slugified into stable field slugs (e.g.
name (required), an optional slug and description, and the fields array.Company → company) — you reference rows by those slugs. An invalid spec (unknown type, a link_to_record with no link_target) returns 400.Write rows
A row is a JSON object keyed by field slug.POST /v1/api/tables/{id}/rows inserts one or many.
PATCH /v1/api/tables/{id}/rows/{row_id} — only the slugs you include change:
DELETE /v1/api/tables/{id}/rows/{row_id} (→ { "deleted": true }). A missing row returns 404. References: Insert rows, Update a row, Delete a row.
Query rows
POST /v1/api/tables/{id}/rows/query reads rows with filters, sorting, projection, and pagination. An empty body returns the first page of all rows.
filters— each{ "field": "<slug>", "op": "<op>", "value": <any> }. Operators:eq,neq,gt,gte,lt,lte,contains,is_empty,is_not_empty. Multiple filters combine with AND.sorts— each{ "field": "<slug>", "desc": <bool> }.select— field slugs to return; omit for all fields.limit/offset— page the result set.
Evolve the schema
Add a field at any time withPOST /v1/api/tables/{id}/fields (the same field shape as create):
DELETE /v1/api/tables/{id}/fields/{field_id}, and delete a whole table with DELETE /v1/api/tables/{id}.
References: Add a field, Drop a field, Delete a table.
Export to CSV
GET /v1/api/tables/{id}/export.csv streams the whole table as a UTF-8 CSV attachment (RFC 4180, with a BOM for Excel and formula-injection defanged). It’s keyset-paged server-side, so the download is constant-memory and never capped at a page size.
tables:read. See Export a table as CSV.
Provenance and audit
Every table and row carries system columns —created_by, updated_by, timestamps — populated from the identity chain, so each row records whether a human or a specific agent (and which conversation) wrote it. Every mutation also emits an event to the always-on audit log. This per-row, tamper-evident provenance is what makes agent-written data accountable — see the security concept.