Data API
The schema model for app-private dynamic tables, and the HTTP data API for reading and writing rows from outside the app
AxHub apps store data in app-private dynamic tables — no separate database to wire up. Each app gets an isolated PostgreSQL schema where you define tables and columns and CRUD rows. This page covers the schema model and the HTTP data API you call from outside the app. Inside the app the SDK is simpler (see Call the backend with the SDK); for a step-by-step walkthrough see the Dynamic tables guide.
Access model
The data surface splits into two sides with different authentication.
| Operation | Auth |
|---|---|
| DDL — create/alter tables, columns, grants | Login (OAuth) only |
| Data — read/write rows | Login (OAuth) or PAT (X-Api-Key) |
- In-app code → SDK (acts as the signed-in user, simplest)
- Outside the app (agents, CI, server-to-server) → HTTP data API + PAT
Creating and managing tables (DDL) can't be done with a PAT — it needs a login. PATs are for reading and writing data only.
Schema model
A table is defined by its columns. The column format is name:type[:nullable][:default].
axhub tables create orders --app demo \
--column 'title:text' \
--column 'qty:int' \
--column 'done:bool:true:false' \
--executeThere are 8 column types.
| Type | Description |
|---|---|
text | String |
int · bigint | Integer |
float | Float |
bool | Boolean |
timestamptz | Timestamp with time zone |
uuid | UUID |
jsonb | JSON |
- owner-column —
--owner-column <column>marks the column that identifies a row's owner. - description — a table description is capped at 1000 bytes (~1000 ASCII chars).
- For many columns, pass a schema file with
--schema table.yaml.
Data API endpoints
To work with rows from outside, call HTTP directly. The path is /data/{tenant}/{app}/{table} and the base is https://api.axhub.ai.
| Method · Path | Does |
|---|---|
GET /data/{tenant}/{app}/{table} | List rows |
GET …/{table}/_count | Count rows |
GET …/{table}/{id} | Get one row |
POST …/{table} | Insert a row |
PATCH …/{table}/{id} | Update a row |
DELETE …/{table}/{id} | Delete a row |
const base = `https://api.axhub.ai/data/${tenant}/${app}/orders`;
const headers = { 'X-Api-Key': process.env.AXHUB_API_KEY, 'Content-Type': 'application/json' };
const rows = await fetch(base, { headers }).then((r) => r.json()); // list
await fetch(base, { // insert
method: 'POST', headers, body: JSON.stringify({ title: 'First order', qty: 2 }),
});Query parameters
List (GET) and count (_count) accept these query parameters to filter and sort.
| Parameter | Description |
|---|---|
filter | Backend DSL: col=value or col=op.value (e.g. qty=gt.10) |
select | Columns to return, comma-separated |
sort | Sort columns, comma-separated; prefix with - for DESC (e.g. -created_at) |
page · per_page | Pagination (per_page max 200) |
To insert many rows at once, send JSONL (one JSON object per line). Batch insert requests are throttled to 200/min.
Table grants
By default a table is reachable only by the app that created it. To open read/write access to another app or principal, issue a table grant.
axhub tables grants issue --app demo --table orders \
--principal-type <principal kind> --principal-id <principal id> \
--actions read,write --execute
axhub tables grants list --app demo --table orders
axhub tables grants revoke --app demo --table orders --grant-id <grant id>A grant is a principal plus actions — who (principal-type·principal-id) can do what (read/write, etc.).
Security & errors
- A PAT (
X-Api-Key) is a secret. Don't hard-code it — store it as aruntimesecret in environment variables and read it on the server. - DDL is not allowed with a PAT — table, column, and grant changes require a login (OAuth).
- Responses are JSON; failures are traceable via
X-Request-Id. Automation should prefer HTTP status + request id over localized messages.