2026-10-22
Database is a headless content store: structured tables and rows that people, agents and scripts read and write directly through the API, the way a headless CMS works. Concepts and behavior follow Supabase (PostgREST filters, projections, ordering and row writes via supabase-js), so Supabase experience applies. Differences: storage uses SQLite, not PostgreSQL, and schema changes use table/field APIs rather than SQL migrations or raw SQL; access uses a Praxis credential scoped to its tenant, with no Supabase Auth or row-level security policies; realtime row subscriptions are unavailable; casts, aggregates, spread and join modifiers are unsupported, and filtered planned/estimated counts may be unknown; upsert targets id or one unique field rather than composite keys. For an application's own runtime data, use the application's own d1, kv or r2 components instead. Start with praxis.database.databases.create to create a database, then use its returned id for tables and rows.
Use your API Key as a Bearer credential to manage databases and table structure.
https://api.deepraxis.ai/database/v1
POST /database/v1/databases
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Display name for the database: 1–64 visible characters after trimming; control characters are rejected. It is not an identifier, so later calls still use the returned id. |
| labels | object | no | Optional string tags to attach, at most 64. Each key starts with a lowercase letter and may use up to 63 characters of a-z 0-9 _ -; each value is up to 63 characters of a-z 0-9 _ -. List calls filter on exact key and value pairs. |
Returns: Database.
Success
application/json
| Name | Type | Description |
|---|---|---|
| id | string | Database identifier, prefixed db_. Pass it as database_id in every database, table, field, rows and events path. |
| name | string | Display name given at creation or by the last update; it is not an identifier. |
| labels | object | String tags attached to the database, as key and value pairs; empty object when none. |
| status | string | Lifecycle state of the database. Table, field and row calls work only while it is active. |
| table_count | integer | Number of tables currently in the database, at most 50; refreshed when the schema changes. |
| size_bytes | integer | Storage size; row writes and GET refresh usage at most once per five seconds, schema changes refresh immediately. |
| created_at | string | Time the database was created, as an RFC 3339 UTC timestamp. |
| updated_at | string | Time of the last change to the name, labels, status or usage snapshot, as an RFC 3339 UTC timestamp. |
| deleted_at | string | null | Time the database entered the deleting state, as an RFC 3339 UTC timestamp; null while it is active and again after a restore. |
| purge_at | string | null | Permanent deletion deadline for deleting databases; null otherwise. |
curl -X POST "https://api.deepraxis.ai/database/v1/databases" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"walk-lib-r1-DOC-5320-tasks","labels":{"purpose":"docs","sample":"walk-lib-r1-doc-5320-"}}'Response example — HTTP 201
{
"id": "db_d6f0d743d5a645e8",
"name": "walk-lib-r1-DOC-5320-tasks",
"labels": {
"purpose": "docs",
"sample": "walk-lib-r1-doc-5320-"
},
"status": "active",
"table_count": 0,
"size_bytes": 53248,
"created_at": "2026-10-11T17:41:40.620Z",
"updated_at": "2026-10-11T17:41:41.488Z",
"deleted_at": null,
"purge_at": null
}GET /database/v1/databases
| Parameter | Location | Description |
|---|---|---|
| cursor | query | Opaque next_cursor from the previous page. |
| limit | query | Page size. (default: 20) (1–100) |
| labels | query | Exact label match, encoded as labels[purpose]=docs. |
| status | query | Filter by lifecycle state. active (the default when omitted) lists usable databases; deleting lists databases that were deleted and are still inside the seven-day restore window. Any other value returns 400 INVALID_PARAMS. |
Returns: Page + object.
Success
application/json
| Name | Type | Description |
|---|---|---|
| data | array<object> | Databases on this page, newest first (created_at descending, ties by id). Deleting databases are excluded unless status=deleting. |
| data[].id | string | Database identifier, prefixed db_. Pass it as database_id in every database, table, field, rows and events path. |
| data[].name | string | Display name given at creation or by the last update; it is not an identifier. |
| data[].labels | object | String tags attached to the database, as key and value pairs; empty object when none. |
| data[].status | string | Lifecycle state of the database. Table, field and row calls work only while it is active. |
| data[].table_count | integer | Number of tables currently in the database, at most 50; refreshed when the schema changes. |
| data[].size_bytes | integer | Storage size; row writes and GET refresh usage at most once per five seconds, schema changes refresh immediately. |
| data[].created_at | string | Time the database was created, as an RFC 3339 UTC timestamp. |
| data[].updated_at | string | Time of the last change to the name, labels, status or usage snapshot, as an RFC 3339 UTC timestamp. |
| data[].deleted_at | string | null | Time the database entered the deleting state, as an RFC 3339 UTC timestamp; null while it is active and again after a restore. |
| data[].purge_at | string | null | Permanent deletion deadline for deleting databases; null otherwise. |
| next_cursor | string | null | Opaque cursor for the next page, or null when there are no more items. Databases list: pass it as cursor. Events list: pass it as after_seq (order asc) or before_seq (order desc). |
curl -g -X GET "https://api.deepraxis.ai/database/v1/databases?limit=10&labels[purpose]=docs&labels[sample]=walk-lib-r1-doc-5320-" \
-H "Authorization: Bearer $PRAXIS_API_KEY"Response example — HTTP 200
{
"data": [
{
"id": "db_d6f0d743d5a645e8",
"name": "walk-lib-r1-DOC-5320-tasks",
"labels": {
"purpose": "docs",
"sample": "walk-lib-r1-doc-5320-"
},
"status": "active",
"table_count": 0,
"size_bytes": 53248,
"created_at": "2026-10-11T17:41:40.620Z",
"updated_at": "2026-10-11T17:41:41.488Z",
"deleted_at": null,
"purge_at": null
}
],
"next_cursor": null
}GET /database/v1/databases/{database_id}
| Parameter | Location | Description |
|---|---|---|
| database_id | path | Identifier of the database to act on: the id (db_…) returned by databaseCreateDatabase or databaseListDatabases. A display name is not accepted. |
Returns: Database.
Success
application/json
| Name | Type | Description |
|---|---|---|
| id | string | Database identifier, prefixed db_. Pass it as database_id in every database, table, field, rows and events path. |
| name | string | Display name given at creation or by the last update; it is not an identifier. |
| labels | object | String tags attached to the database, as key and value pairs; empty object when none. |
| status | string | Lifecycle state of the database. Table, field and row calls work only while it is active. |
| table_count | integer | Number of tables currently in the database, at most 50; refreshed when the schema changes. |
| size_bytes | integer | Storage size; row writes and GET refresh usage at most once per five seconds, schema changes refresh immediately. |
| created_at | string | Time the database was created, as an RFC 3339 UTC timestamp. |
| updated_at | string | Time of the last change to the name, labels, status or usage snapshot, as an RFC 3339 UTC timestamp. |
| deleted_at | string | null | Time the database entered the deleting state, as an RFC 3339 UTC timestamp; null while it is active and again after a restore. |
| purge_at | string | null | Permanent deletion deadline for deleting databases; null otherwise. |
curl -X GET "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}" \
-H "Authorization: Bearer $PRAXIS_API_KEY"Response example — HTTP 200
{
"id": "db_d6f0d743d5a645e8",
"name": "walk-lib-r1-DOC-5320-tasks",
"labels": {
"purpose": "docs",
"sample": "walk-lib-r1-doc-5320-"
},
"status": "active",
"table_count": 0,
"size_bytes": 53248,
"created_at": "2026-10-11T17:41:40.620Z",
"updated_at": "2026-10-11T17:41:41.488Z",
"deleted_at": null,
"purge_at": null
}PATCH /database/v1/databases/{database_id}
| Parameter | Location | Description |
|---|---|---|
| database_id | path | Identifier of the database to act on: the id (db_…) returned by databaseCreateDatabase or databaseListDatabases. A display name is not accepted. |
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | no | New display name, 1–64 visible characters after trimming. Omit it to keep the current name. |
| labels | object | no | Complete replacement label set, not a merge: labels not listed here are removed. Same limits as at creation (at most 64; keys a-z 0-9 _ - starting with a letter; values up to 63 characters of a-z 0-9 _ -). Omit it to keep the current labels. |
Returns: Database.
Success
application/json
| Name | Type | Description |
|---|---|---|
| id | string | Database identifier, prefixed db_. Pass it as database_id in every database, table, field, rows and events path. |
| name | string | Display name given at creation or by the last update; it is not an identifier. |
| labels | object | String tags attached to the database, as key and value pairs; empty object when none. |
| status | string | Lifecycle state of the database. Table, field and row calls work only while it is active. |
| table_count | integer | Number of tables currently in the database, at most 50; refreshed when the schema changes. |
| size_bytes | integer | Storage size; row writes and GET refresh usage at most once per five seconds, schema changes refresh immediately. |
| created_at | string | Time the database was created, as an RFC 3339 UTC timestamp. |
| updated_at | string | Time of the last change to the name, labels, status or usage snapshot, as an RFC 3339 UTC timestamp. |
| deleted_at | string | null | Time the database entered the deleting state, as an RFC 3339 UTC timestamp; null while it is active and again after a restore. |
| purge_at | string | null | Permanent deletion deadline for deleting databases; null otherwise. |
curl -X PATCH "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"walk-lib-r1-DOC-5320-notes"}'Response example — HTTP 200
{
"id": "db_d6f0d743d5a645e8",
"name": "walk-lib-r1-DOC-5320-notes",
"labels": {
"purpose": "docs",
"sample": "walk-lib-r1-doc-5320-"
},
"status": "active",
"table_count": 0,
"size_bytes": 53248,
"created_at": "2026-10-11T17:41:40.620Z",
"updated_at": "2026-10-11T17:41:43.514Z",
"deleted_at": null,
"purge_at": null
}DELETE /database/v1/databases/{database_id}
| Parameter | Location | Description |
|---|---|---|
| database_id | path | Identifier of the database to act on: the id (db_…) returned by databaseCreateDatabase or databaseListDatabases. A display name is not accepted. |
Returns: Database.
Success
application/json
| Name | Type | Description |
|---|---|---|
| id | string | Database identifier, prefixed db_. Pass it as database_id in every database, table, field, rows and events path. |
| name | string | Display name given at creation or by the last update; it is not an identifier. |
| labels | object | String tags attached to the database, as key and value pairs; empty object when none. |
| status | string | Lifecycle state of the database. Table, field and row calls work only while it is active. |
| table_count | integer | Number of tables currently in the database, at most 50; refreshed when the schema changes. |
| size_bytes | integer | Storage size; row writes and GET refresh usage at most once per five seconds, schema changes refresh immediately. |
| created_at | string | Time the database was created, as an RFC 3339 UTC timestamp. |
| updated_at | string | Time of the last change to the name, labels, status or usage snapshot, as an RFC 3339 UTC timestamp. |
| deleted_at | string | null | Time the database entered the deleting state, as an RFC 3339 UTC timestamp; null while it is active and again after a restore. |
| purge_at | string | null | Permanent deletion deadline for deleting databases; null otherwise. |
curl -X DELETE "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}" \
-H "Authorization: Bearer $PRAXIS_API_KEY"Response example — HTTP 200
{
"id": "db_d6f0d743d5a645e8",
"name": "walk-lib-r1-DOC-5320-notes",
"labels": {
"purpose": "docs",
"sample": "walk-lib-r1-doc-5320-"
},
"status": "deleting",
"table_count": 0,
"size_bytes": 53248,
"created_at": "2026-10-11T17:41:40.620Z",
"updated_at": "2026-10-11T17:41:51.868Z",
"deleted_at": "2026-10-11T17:41:51.868Z",
"purge_at": "2026-10-18T17:41:51.868Z"
}POST /database/v1/databases/{database_id}/restore
| Parameter | Location | Description |
|---|---|---|
| database_id | path | Identifier of the database to act on: the id (db_…) returned by databaseCreateDatabase or databaseListDatabases. A display name is not accepted. |
Returns: Database.
Success
application/json
| Name | Type | Description |
|---|---|---|
| id | string | Database identifier, prefixed db_. Pass it as database_id in every database, table, field, rows and events path. |
| name | string | Display name given at creation or by the last update; it is not an identifier. |
| labels | object | String tags attached to the database, as key and value pairs; empty object when none. |
| status | string | Lifecycle state of the database. Table, field and row calls work only while it is active. |
| table_count | integer | Number of tables currently in the database, at most 50; refreshed when the schema changes. |
| size_bytes | integer | Storage size; row writes and GET refresh usage at most once per five seconds, schema changes refresh immediately. |
| created_at | string | Time the database was created, as an RFC 3339 UTC timestamp. |
| updated_at | string | Time of the last change to the name, labels, status or usage snapshot, as an RFC 3339 UTC timestamp. |
| deleted_at | string | null | Time the database entered the deleting state, as an RFC 3339 UTC timestamp; null while it is active and again after a restore. |
| purge_at | string | null | Permanent deletion deadline for deleting databases; null otherwise. |
curl -X POST "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/restore" \
-H "Authorization: Bearer $PRAXIS_API_KEY"Response example — HTTP 200
{
"id": "db_d6f0d743d5a645e8",
"name": "walk-lib-r1-DOC-5320-notes",
"labels": {
"purpose": "docs",
"sample": "walk-lib-r1-doc-5320-"
},
"status": "active",
"table_count": 0,
"size_bytes": 53248,
"created_at": "2026-10-11T17:41:40.620Z",
"updated_at": "2026-10-11T17:41:51.528Z",
"deleted_at": null,
"purge_at": null
}POST /database/v1/databases/{database_id}/purge
| Parameter | Location | Description |
|---|---|---|
| database_id | path | Identifier of the database to act on: the id (db_…) returned by databaseCreateDatabase or databaseListDatabases. A display name is not accepted. |
Returns: object.
Permanently purged
application/json
| Name | Type | Description |
|---|---|---|
| id | string | Id (db_…) of the database that was permanently purged; it no longer resolves. |
| object | string | Resource type of the purged object; always database. |
| purged | boolean | Always true: the database and all of its data were permanently removed and cannot be recovered. |
curl -X POST "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/purge" \
-H "Authorization: Bearer $PRAXIS_API_KEY"Response example — HTTP 200
{
"id": "db_d6f0d743d5a645e8",
"object": "database",
"purged": true
}| Field | Type | Required | Description |
|---|---|---|---|
| id | string | yes | Database identifier, prefixed db_. Pass it as database_id in every database, table, field, rows and events path.; ^db_ |
| name | string | yes | Display name given at creation or by the last update; it is not an identifier. |
| labels | object | yes | String tags attached to the database, as key and value pairs; empty object when none. |
| status | "provisioning" / "active" / "deleting" / "deleted" / "failed" | yes | Lifecycle state of the database. Table, field and row calls work only while it is active. |
| table_count | integer | yes | Number of tables currently in the database, at most 50; refreshed when the schema changes. |
| size_bytes | integer | yes | Storage size; row writes and GET refresh usage at most once per five seconds, schema changes refresh immediately. |
| created_at | date-time | yes | Time the database was created, as an RFC 3339 UTC timestamp. |
| updated_at | date-time | yes | Time of the last change to the name, labels, status or usage snapshot, as an RFC 3339 UTC timestamp. |
| deleted_at | date-time / null | yes | Time the database entered the deleting state, as an RFC 3339 UTC timestamp; null while it is active and again after a restore. |
| purge_at | date-time / null | yes | Permanent deletion deadline for deleting databases; null otherwise. |
| Field | Type | Required | Description |
|---|---|---|---|
| data | JSON[] | yes | Items of this page; the item type depends on the operation. |
| next_cursor | string / null | yes | Opaque cursor for the next page, or null when there are no more items. Databases list: pass it as cursor. Events list: pass it as after_seq (order asc) or before_seq (order desc). |
POST /database/v1/databases/{database_id}/tables
| Parameter | Location | Description |
|---|---|---|
| database_id | path | Identifier of the database to act on: the id (db_…) returned by databaseCreateDatabase or databaseListDatabases. A display name is not accepted. |
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Table name used in the rows path and in link references. Must match ^[a-z_][a-z0-9_]{0,62}$ and be unused in this database; it can be renamed later without affecting data.; ^[a-z_][a-z0-9_]{0,62}$ |
| description | string | no | Optional free-text note describing what the table stores. Returned as description on the table; omit it to store null. |
| fields | NewField[] | yes | Initial field definitions, in display order; may be an empty array. At most 64 fields per table and at most 16 indexed or unique fields. Each item follows the NewField shape selected by its type. |
Returns: Table.
Success
application/json
| Name | Type | Description |
|---|---|---|
| id | string | Table identifier, prefixed tbl_. Stable across renames and accepted wherever a table path parameter takes an id or name. |
| name | string | Current table name, usable in the rows path; may change when the table is renamed. |
| description | string | null | Free-text note about the table, or null when none was set. |
| fields | array<object> | Field definitions of the table, in display order. Row values are keyed by each field's name. |
| fields[].id | string | Field identifier, prefixed fld_. Stable across renames; accepted wherever a field path parameter takes an id or name. |
| fields[].name | string | Current field name; rows are keyed by it in requests and responses. May change when the field is renamed. |
| fields[].description | string | null | Free-text note about the field, or null when none was set. |
| fields[].required | boolean | Whether every row must hold a non-null value for this field. |
| fields[].unique | boolean | Whether values must be distinct across rows; fixed at creation. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| fields[].indexed | boolean | Whether an index is maintained for faster filters and ordering. Always false for json and link fields. |
| fields[].type | string | Scalar data type of the field; it cannot be changed after the field is created. / Type json: the value is any JSON document validated against options.schema. It cannot be changed after the field is created. / Type link: the value is the id of a row in another table (an array of ids when options.multiple is true). It cannot be changed after the field is created. |
| fields[].options | object | Scalar fields take no options; always an empty object. / Settings of a json field. schema is required. / Settings of a link field. Both linked_table_id and multiple are required. |
| fields[].default | any | Default JSON value for omitted insert fields; must match the field type and JSON schema. A datetime default of "now()" evaluates to server time on insertion and reads back as "now()" in the field definition. For string and json fields it is a literal string. Explicit null remains null. Link fields do not support defaults. |
| schema_revision | integer | Counter that starts at 1 and increases by one each time the table's name, description or fields change; use it to detect schema changes. |
| created_at | string | Time the table was created, as an RFC 3339 UTC timestamp. |
| updated_at | string | Time of the last schema change to the table, as an RFC 3339 UTC timestamp. |
| row_count | integer | Number of rows currently stored. Returned only by databaseGetTable; absent from list, create and field responses. |
curl -X POST "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/tables" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"tasks","fields":[{"name":"title","type":"string","required":true,"unique":true},{"name":"done","type":"boolean"}]}'Response example — HTTP 201
{
"id": "tbl_2b3431c772754599",
"name": "tasks",
"description": null,
"schema_revision": 1,
"created_at": "2026-10-11T17:41:44.246Z",
"updated_at": "2026-10-11T17:41:44.246Z",
"fields": [
{
"id": "fld_bc71f7c6a1a848d2",
"name": "title",
"type": "string",
"description": null,
"required": true,
"unique": true,
"indexed": true
},
{
"id": "fld_c7879883dfe04ca0",
"name": "done",
"type": "boolean",
"description": null,
"required": false,
"unique": false,
"indexed": true
}
]
}GET /database/v1/databases/{database_id}/tables
| Parameter | Location | Description |
|---|---|---|
| database_id | path | Identifier of the database to act on: the id (db_…) returned by databaseCreateDatabase or databaseListDatabases. A display name is not accepted. |
Returns: Page + object.
Success
application/json
| Name | Type | Description |
|---|---|---|
| data | array<object> | Every table of the database with its fields, in creation order; at most 50 items. |
| data[].id | string | Table identifier, prefixed tbl_. Stable across renames and accepted wherever a table path parameter takes an id or name. |
| data[].name | string | Current table name, usable in the rows path; may change when the table is renamed. |
| data[].description | string | null | Free-text note about the table, or null when none was set. |
| data[].fields | array<object> | Field definitions of the table, in display order. Row values are keyed by each field's name. |
| data[].schema_revision | integer | Counter that starts at 1 and increases by one each time the table's name, description or fields change; use it to detect schema changes. |
| data[].created_at | string | Time the table was created, as an RFC 3339 UTC timestamp. |
| data[].updated_at | string | Time of the last schema change to the table, as an RFC 3339 UTC timestamp. |
| data[].row_count | integer | Number of rows currently stored. Returned only by databaseGetTable; absent from list, create and field responses. |
| next_cursor | string | null | Opaque cursor for the next page, or null when there are no more items. Databases list: pass it as cursor. Events list: pass it as after_seq (order asc) or before_seq (order desc). |
curl -X GET "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/tables" \
-H "Authorization: Bearer $PRAXIS_API_KEY"Response example — HTTP 200
{
"data": [
{
"id": "tbl_2b3431c772754599",
"name": "tasks",
"description": null,
"schema_revision": 1,
"created_at": "2026-10-11T17:41:44.246Z",
"updated_at": "2026-10-11T17:41:44.246Z",
"fields": [
{
"id": "fld_bc71f7c6a1a848d2",
"name": "title",
"type": "string",
"description": null,
"required": true,
"unique": true,
"indexed": true
},
{
"id": "fld_c7879883dfe04ca0",
"name": "done",
"type": "boolean",
"description": null,
"required": false,
"unique": false,
"indexed": true
}
]
}
],
"next_cursor": null
}GET /database/v1/databases/{database_id}/tables/{table}
| Parameter | Location | Description |
|---|---|---|
| database_id | path | Identifier of the database to act on: the id (db_…) returned by databaseCreateDatabase or databaseListDatabases. A display name is not accepted. |
| table | path | table ID or name. |
Returns: Table.
Success
application/json
| Name | Type | Description |
|---|---|---|
| id | string | Table identifier, prefixed tbl_. Stable across renames and accepted wherever a table path parameter takes an id or name. |
| name | string | Current table name, usable in the rows path; may change when the table is renamed. |
| description | string | null | Free-text note about the table, or null when none was set. |
| fields | array<object> | Field definitions of the table, in display order. Row values are keyed by each field's name. |
| fields[].id | string | Field identifier, prefixed fld_. Stable across renames; accepted wherever a field path parameter takes an id or name. |
| fields[].name | string | Current field name; rows are keyed by it in requests and responses. May change when the field is renamed. |
| fields[].description | string | null | Free-text note about the field, or null when none was set. |
| fields[].required | boolean | Whether every row must hold a non-null value for this field. |
| fields[].unique | boolean | Whether values must be distinct across rows; fixed at creation. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| fields[].indexed | boolean | Whether an index is maintained for faster filters and ordering. Always false for json and link fields. |
| fields[].type | string | Scalar data type of the field; it cannot be changed after the field is created. / Type json: the value is any JSON document validated against options.schema. It cannot be changed after the field is created. / Type link: the value is the id of a row in another table (an array of ids when options.multiple is true). It cannot be changed after the field is created. |
| fields[].options | object | Scalar fields take no options; always an empty object. / Settings of a json field. schema is required. / Settings of a link field. Both linked_table_id and multiple are required. |
| fields[].default | any | Default JSON value for omitted insert fields; must match the field type and JSON schema. A datetime default of "now()" evaluates to server time on insertion and reads back as "now()" in the field definition. For string and json fields it is a literal string. Explicit null remains null. Link fields do not support defaults. |
| schema_revision | integer | Counter that starts at 1 and increases by one each time the table's name, description or fields change; use it to detect schema changes. |
| created_at | string | Time the table was created, as an RFC 3339 UTC timestamp. |
| updated_at | string | Time of the last schema change to the table, as an RFC 3339 UTC timestamp. |
| row_count | integer | Number of rows currently stored. Returned only by databaseGetTable; absent from list, create and field responses. |
curl -X GET "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/tables/tasks" \
-H "Authorization: Bearer $PRAXIS_API_KEY"Response example — HTTP 200
{
"id": "tbl_2b3431c772754599",
"name": "tasks",
"description": null,
"schema_revision": 1,
"created_at": "2026-10-11T17:41:44.246Z",
"updated_at": "2026-10-11T17:41:44.246Z",
"fields": [
{
"id": "fld_bc71f7c6a1a848d2",
"name": "title",
"type": "string",
"description": null,
"required": true,
"unique": true,
"indexed": true
},
{
"id": "fld_c7879883dfe04ca0",
"name": "done",
"type": "boolean",
"description": null,
"required": false,
"unique": false,
"indexed": true
}
],
"row_count": 0
}PATCH /database/v1/databases/{database_id}/tables/{table}
| Parameter | Location | Description |
|---|---|---|
| database_id | path | Identifier of the database to act on: the id (db_…) returned by databaseCreateDatabase or databaseListDatabases. A display name is not accepted. |
| table | path | table ID or name. |
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | no | New table name matching ^[a-z_][a-z0-9_]{0,62}$ and unused in this database. Omit it to keep the current name. |
| description | string / null | no | New description text, or null to clear it. Omit it to keep the current description. |
Returns: Table.
Success
application/json
| Name | Type | Description |
|---|---|---|
| id | string | Table identifier, prefixed tbl_. Stable across renames and accepted wherever a table path parameter takes an id or name. |
| name | string | Current table name, usable in the rows path; may change when the table is renamed. |
| description | string | null | Free-text note about the table, or null when none was set. |
| fields | array<object> | Field definitions of the table, in display order. Row values are keyed by each field's name. |
| fields[].id | string | Field identifier, prefixed fld_. Stable across renames; accepted wherever a field path parameter takes an id or name. |
| fields[].name | string | Current field name; rows are keyed by it in requests and responses. May change when the field is renamed. |
| fields[].description | string | null | Free-text note about the field, or null when none was set. |
| fields[].required | boolean | Whether every row must hold a non-null value for this field. |
| fields[].unique | boolean | Whether values must be distinct across rows; fixed at creation. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| fields[].indexed | boolean | Whether an index is maintained for faster filters and ordering. Always false for json and link fields. |
| fields[].type | string | Scalar data type of the field; it cannot be changed after the field is created. / Type json: the value is any JSON document validated against options.schema. It cannot be changed after the field is created. / Type link: the value is the id of a row in another table (an array of ids when options.multiple is true). It cannot be changed after the field is created. |
| fields[].options | object | Scalar fields take no options; always an empty object. / Settings of a json field. schema is required. / Settings of a link field. Both linked_table_id and multiple are required. |
| fields[].default | any | Default JSON value for omitted insert fields; must match the field type and JSON schema. A datetime default of "now()" evaluates to server time on insertion and reads back as "now()" in the field definition. For string and json fields it is a literal string. Explicit null remains null. Link fields do not support defaults. |
| schema_revision | integer | Counter that starts at 1 and increases by one each time the table's name, description or fields change; use it to detect schema changes. |
| created_at | string | Time the table was created, as an RFC 3339 UTC timestamp. |
| updated_at | string | Time of the last schema change to the table, as an RFC 3339 UTC timestamp. |
| row_count | integer | Number of rows currently stored. Returned only by databaseGetTable; absent from list, create and field responses. |
curl -X PATCH "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/tables/tasks" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"description":"Tasks for an agent"}'Response example — HTTP 200
{
"id": "tbl_2b3431c772754599",
"name": "tasks",
"description": "Tasks for an agent",
"schema_revision": 2,
"created_at": "2026-10-11T17:41:44.246Z",
"updated_at": "2026-10-11T17:41:45.127Z",
"fields": [
{
"id": "fld_bc71f7c6a1a848d2",
"name": "title",
"type": "string",
"description": null,
"required": true,
"unique": true,
"indexed": true
},
{
"id": "fld_c7879883dfe04ca0",
"name": "done",
"type": "boolean",
"description": null,
"required": false,
"unique": false,
"indexed": true
}
]
}DELETE /database/v1/databases/{database_id}/tables/{table}
| Parameter | Location | Description |
|---|---|---|
| database_id | path | Identifier of the database to act on: the id (db_…) returned by databaseCreateDatabase or databaseListDatabases. A display name is not accepted. |
| table | path | table ID or name. |
Returns: object.
Success
application/json
| Name | Type | Description |
|---|---|---|
| deleted | boolean | Always true: the table and all of its rows were dropped immediately and cannot be recovered. |
curl -X DELETE "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/tables/tasks" \
-H "Authorization: Bearer $PRAXIS_API_KEY"Response example — HTTP 200
{
"deleted": true
}| Field | Type | Required | Description |
|---|---|---|---|
| id | string | yes | Table identifier, prefixed tbl_. Stable across renames and accepted wherever a table path parameter takes an id or name.; ^tbl_ |
| name | string | yes | Current table name, usable in the rows path; may change when the table is renamed. |
| description | string / null | yes | Free-text note about the table, or null when none was set. |
| fields | Field[] | yes | Field definitions of the table, in display order. Row values are keyed by each field's name. |
| schema_revision | integer | yes | Counter that starts at 1 and increases by one each time the table's name, description or fields change; use it to detect schema changes. |
| created_at | date-time | yes | Time the table was created, as an RFC 3339 UTC timestamp. |
| updated_at | date-time | yes | Time of the last schema change to the table, as an RFC 3339 UTC timestamp. |
| row_count | integer | no | Number of rows currently stored. Returned only by databaseGetTable; absent from list, create and field responses. |
Adding, updating or deleting a field returns the complete Table. Field types and link targets are immutable. JSON Schema updates apply to subsequent writes.
A new field with a default fills every existing row with it, required or not, without changing row versions; a new field without a default is null on existing rows. Adding a required field to a table that already has rows needs a default; without one the request returns 400 VALIDATION_FAILED. Making a field required while some rows are null in it returns 400 VALIDATION_FAILED, with the number of null rows in the message. A PATCH with an empty body, only ignored keys, or only values equal to the current ones changes neither updated_at nor schema_revision, records no event and returns the current object.
A datetime default can be the string "now()": insertion evaluates it to current server UTC time, while the field definition still returns "now()". Example: {"name":"created_at","type":"datetime","default":"now()"}. String/json fields keep the literal; other types retain normal validation. Adding a field also evaluates this default when backfilling existing rows.
POST /database/v1/databases/{database_id}/tables/{table}/fields
| Parameter | Location | Description |
|---|---|---|
| database_id | path | Identifier of the database to act on: the id (db_…) returned by databaseCreateDatabase or databaseListDatabases. A display name is not accepted. |
| table | path | table ID or name. |
"string" / "integer" / "number" / "boolean" / "datetime"
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Field name. Only id is reserved; new field names cannot start with _ (reserved for system metadata). created_at, updated_at and version are ordinary user field names. Existing underscore-prefixed fields remain usable and take precedence over metadata.; ^(?!id$)[a-z][a-z0-9_]{0,62}$ |
| description | string | no | Optional free-text note about the field; omit it to store null. |
| required | boolean | no | Whether every row must hold a non-null value for this field. Defaults to false. |
| unique | boolean | no | Whether values must be distinct across rows. Defaults to false; cannot be changed after the field exists. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| indexed | boolean | no | Whether to maintain an index for faster filters and ordering. Defaults to true for scalar types and is not allowed for json and link fields. At most 16 indexed or unique fields per table. |
| type | "string" / "integer" / "number" / "boolean" / "datetime" | yes | Scalar data type of the field; it cannot be changed after the field is created. |
| options | object | no | Scalar fields take no options; always an empty object. |
| default | JSON | no | Default JSON value for omitted insert fields; must match the field type and JSON schema. A datetime default of "now()" evaluates to server time on insertion and reads back as "now()" in the field definition. For string and json fields it is a literal string. Explicit null remains null. Link fields do not support defaults. |
"json"
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Field name. Only id is reserved; new field names cannot start with _ (reserved for system metadata). created_at, updated_at and version are ordinary user field names. Existing underscore-prefixed fields remain usable and take precedence over metadata.; ^(?!id$)[a-z][a-z0-9_]{0,62}$ |
| description | string | no | Optional free-text note about the field; omit it to store null. |
| required | boolean | no | Whether every row must hold a non-null value for this field. Defaults to false. |
| unique | boolean | no | Whether values must be distinct across rows. Defaults to false; cannot be changed after the field exists. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| indexed | boolean | no | Whether to maintain an index for faster filters and ordering. Defaults to true for scalar types and is not allowed for json and link fields. At most 16 indexed or unique fields per table. |
| type | "json" | yes | Type json: the value is any JSON document validated against options.schema. It cannot be changed after the field is created. |
| options | object | yes | Settings of a json field. schema is required. |
| default | JSON | no | Default JSON value for omitted insert fields; must match the field type and JSON schema. A datetime default of "now()" evaluates to server time on insertion and reads back as "now()" in the field definition. For string and json fields it is a literal string. Explicit null remains null. Link fields do not support defaults. |
"link"
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Field name. Only id is reserved; new field names cannot start with _ (reserved for system metadata). created_at, updated_at and version are ordinary user field names. Existing underscore-prefixed fields remain usable and take precedence over metadata.; ^(?!id$)[a-z][a-z0-9_]{0,62}$ |
| description | string | no | Optional free-text note about the field; omit it to store null. |
| required | boolean | no | Whether every row must hold a non-null value for this field. Defaults to false. |
| unique | boolean | no | Whether values must be distinct across rows. Defaults to false; cannot be changed after the field exists. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| indexed | boolean | no | Whether to maintain an index for faster filters and ordering. Defaults to true for scalar types and is not allowed for json and link fields. At most 16 indexed or unique fields per table. |
| type | "link" | yes | Type link: the value is the id of a row in another table (an array of ids when options.multiple is true). It cannot be changed after the field is created. |
| options | object | yes | Settings of a link field. Both linked_table_id and multiple are required. |
Returns: Table.
Success
application/json
| Name | Type | Description |
|---|---|---|
| id | string | Table identifier, prefixed tbl_. Stable across renames and accepted wherever a table path parameter takes an id or name. |
| name | string | Current table name, usable in the rows path; may change when the table is renamed. |
| description | string | null | Free-text note about the table, or null when none was set. |
| fields | array<object> | Field definitions of the table, in display order. Row values are keyed by each field's name. |
| fields[].id | string | Field identifier, prefixed fld_. Stable across renames; accepted wherever a field path parameter takes an id or name. |
| fields[].name | string | Current field name; rows are keyed by it in requests and responses. May change when the field is renamed. |
| fields[].description | string | null | Free-text note about the field, or null when none was set. |
| fields[].required | boolean | Whether every row must hold a non-null value for this field. |
| fields[].unique | boolean | Whether values must be distinct across rows; fixed at creation. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| fields[].indexed | boolean | Whether an index is maintained for faster filters and ordering. Always false for json and link fields. |
| fields[].type | string | Scalar data type of the field; it cannot be changed after the field is created. / Type json: the value is any JSON document validated against options.schema. It cannot be changed after the field is created. / Type link: the value is the id of a row in another table (an array of ids when options.multiple is true). It cannot be changed after the field is created. |
| fields[].options | object | Scalar fields take no options; always an empty object. / Settings of a json field. schema is required. / Settings of a link field. Both linked_table_id and multiple are required. |
| fields[].default | any | Default JSON value for omitted insert fields; must match the field type and JSON schema. A datetime default of "now()" evaluates to server time on insertion and reads back as "now()" in the field definition. For string and json fields it is a literal string. Explicit null remains null. Link fields do not support defaults. |
| schema_revision | integer | Counter that starts at 1 and increases by one each time the table's name, description or fields change; use it to detect schema changes. |
| created_at | string | Time the table was created, as an RFC 3339 UTC timestamp. |
| updated_at | string | Time of the last schema change to the table, as an RFC 3339 UTC timestamp. |
| row_count | integer | Number of rows currently stored. Returned only by databaseGetTable; absent from list, create and field responses. |
curl -X POST "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/tables/tasks/fields" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"priority","type":"integer"}'Response example — HTTP 201
{
"id": "tbl_2b3431c772754599",
"name": "tasks",
"description": "Tasks for an agent",
"schema_revision": 3,
"created_at": "2026-10-11T17:41:44.246Z",
"updated_at": "2026-10-11T17:41:45.420Z",
"fields": [
{
"id": "fld_bc71f7c6a1a848d2",
"name": "title",
"type": "string",
"description": null,
"required": true,
"unique": true,
"indexed": true
},
{
"id": "fld_c7879883dfe04ca0",
"name": "done",
"type": "boolean",
"description": null,
"required": false,
"unique": false,
"indexed": true
},
{
"id": "fld_4c3e63869e35458c",
"name": "priority",
"type": "integer",
"description": null,
"required": false,
"unique": false,
"indexed": true
}
]
}PATCH /database/v1/databases/{database_id}/tables/{table}/fields/{field}
| Parameter | Location | Description |
|---|---|---|
| database_id | path | Identifier of the database to act on: the id (db_…) returned by databaseCreateDatabase or databaseListDatabases. A display name is not accepted. |
| table | path | table ID or name. |
| field | path | field ID or name. |
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | no | New field name (lowercase letters, digits and underscores; id and names starting with _ are reserved). Renaming does not rewrite stored rows. Omit it to keep the current name. |
| description | string / null | no | New description text, or null to clear it. Omit it to keep the current description. |
| required | boolean | no | Whether every row must hold a non-null value for this field. Setting true fails with 400 VALIDATION_FAILED while existing rows have null for the field; fill them first. |
| indexed | boolean | no | Whether to maintain an index on this field to speed up filters and ordering. Only scalar fields (string, integer, number, boolean, datetime) can be indexed; true on json or link fields is rejected, and a table allows at most 16 indexed or unique fields. |
| options | object | no | Type-specific settings. Only json fields accept changes, through options.schema; scalar fields take no options, and a link field's options cannot change. |
| default | JSON | no | Sets the default for future inserts. Must match the current type and JSON schema; not supported for link fields. |
Returns: Table.
Success
application/json
| Name | Type | Description |
|---|---|---|
| id | string | Table identifier, prefixed tbl_. Stable across renames and accepted wherever a table path parameter takes an id or name. |
| name | string | Current table name, usable in the rows path; may change when the table is renamed. |
| description | string | null | Free-text note about the table, or null when none was set. |
| fields | array<object> | Field definitions of the table, in display order. Row values are keyed by each field's name. |
| fields[].id | string | Field identifier, prefixed fld_. Stable across renames; accepted wherever a field path parameter takes an id or name. |
| fields[].name | string | Current field name; rows are keyed by it in requests and responses. May change when the field is renamed. |
| fields[].description | string | null | Free-text note about the field, or null when none was set. |
| fields[].required | boolean | Whether every row must hold a non-null value for this field. |
| fields[].unique | boolean | Whether values must be distinct across rows; fixed at creation. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| fields[].indexed | boolean | Whether an index is maintained for faster filters and ordering. Always false for json and link fields. |
| fields[].type | string | Scalar data type of the field; it cannot be changed after the field is created. / Type json: the value is any JSON document validated against options.schema. It cannot be changed after the field is created. / Type link: the value is the id of a row in another table (an array of ids when options.multiple is true). It cannot be changed after the field is created. |
| fields[].options | object | Scalar fields take no options; always an empty object. / Settings of a json field. schema is required. / Settings of a link field. Both linked_table_id and multiple are required. |
| fields[].default | any | Default JSON value for omitted insert fields; must match the field type and JSON schema. A datetime default of "now()" evaluates to server time on insertion and reads back as "now()" in the field definition. For string and json fields it is a literal string. Explicit null remains null. Link fields do not support defaults. |
| schema_revision | integer | Counter that starts at 1 and increases by one each time the table's name, description or fields change; use it to detect schema changes. |
| created_at | string | Time the table was created, as an RFC 3339 UTC timestamp. |
| updated_at | string | Time of the last schema change to the table, as an RFC 3339 UTC timestamp. |
| row_count | integer | Number of rows currently stored. Returned only by databaseGetTable; absent from list, create and field responses. |
curl -X PATCH "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/tables/tasks/fields/priority" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"description":"Task priority"}'Response example — HTTP 200
{
"id": "tbl_2b3431c772754599",
"name": "tasks",
"description": "Tasks for an agent",
"schema_revision": 4,
"created_at": "2026-10-11T17:41:44.246Z",
"updated_at": "2026-10-11T17:41:46.276Z",
"fields": [
{
"id": "fld_bc71f7c6a1a848d2",
"name": "title",
"type": "string",
"description": null,
"required": true,
"unique": true,
"indexed": true
},
{
"id": "fld_c7879883dfe04ca0",
"name": "done",
"type": "boolean",
"description": null,
"required": false,
"unique": false,
"indexed": true
},
{
"id": "fld_4c3e63869e35458c",
"name": "priority",
"type": "integer",
"description": "Task priority",
"required": false,
"unique": false,
"indexed": true
}
]
}DELETE /database/v1/databases/{database_id}/tables/{table}/fields/{field}
| Parameter | Location | Description |
|---|---|---|
| database_id | path | Identifier of the database to act on: the id (db_…) returned by databaseCreateDatabase or databaseListDatabases. A display name is not accepted. |
| table | path | table ID or name. |
| field | path | field ID or name. |
Returns: Table.
Success
application/json
| Name | Type | Description |
|---|---|---|
| id | string | Table identifier, prefixed tbl_. Stable across renames and accepted wherever a table path parameter takes an id or name. |
| name | string | Current table name, usable in the rows path; may change when the table is renamed. |
| description | string | null | Free-text note about the table, or null when none was set. |
| fields | array<object> | Field definitions of the table, in display order. Row values are keyed by each field's name. |
| fields[].id | string | Field identifier, prefixed fld_. Stable across renames; accepted wherever a field path parameter takes an id or name. |
| fields[].name | string | Current field name; rows are keyed by it in requests and responses. May change when the field is renamed. |
| fields[].description | string | null | Free-text note about the field, or null when none was set. |
| fields[].required | boolean | Whether every row must hold a non-null value for this field. |
| fields[].unique | boolean | Whether values must be distinct across rows; fixed at creation. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| fields[].indexed | boolean | Whether an index is maintained for faster filters and ordering. Always false for json and link fields. |
| fields[].type | string | Scalar data type of the field; it cannot be changed after the field is created. / Type json: the value is any JSON document validated against options.schema. It cannot be changed after the field is created. / Type link: the value is the id of a row in another table (an array of ids when options.multiple is true). It cannot be changed after the field is created. |
| fields[].options | object | Scalar fields take no options; always an empty object. / Settings of a json field. schema is required. / Settings of a link field. Both linked_table_id and multiple are required. |
| fields[].default | any | Default JSON value for omitted insert fields; must match the field type and JSON schema. A datetime default of "now()" evaluates to server time on insertion and reads back as "now()" in the field definition. For string and json fields it is a literal string. Explicit null remains null. Link fields do not support defaults. |
| schema_revision | integer | Counter that starts at 1 and increases by one each time the table's name, description or fields change; use it to detect schema changes. |
| created_at | string | Time the table was created, as an RFC 3339 UTC timestamp. |
| updated_at | string | Time of the last schema change to the table, as an RFC 3339 UTC timestamp. |
| row_count | integer | Number of rows currently stored. Returned only by databaseGetTable; absent from list, create and field responses. |
curl -X DELETE "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/tables/tasks/fields/priority" \
-H "Authorization: Bearer $PRAXIS_API_KEY"Response example — HTTP 200
{
"id": "tbl_2b3431c772754599",
"name": "tasks",
"description": "Tasks for an agent",
"schema_revision": 5,
"created_at": "2026-10-11T17:41:44.246Z",
"updated_at": "2026-10-11T17:41:47.136Z",
"fields": [
{
"id": "fld_bc71f7c6a1a848d2",
"name": "title",
"type": "string",
"description": null,
"required": true,
"unique": true,
"indexed": true
},
{
"id": "fld_c7879883dfe04ca0",
"name": "done",
"type": "boolean",
"description": null,
"required": false,
"unique": false,
"indexed": true
}
]
}"string" / "integer" / "number" / "boolean" / "datetime"
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | yes | Field identifier, prefixed fld_. Stable across renames; accepted wherever a field path parameter takes an id or name. |
| name | string | yes | Current field name; rows are keyed by it in requests and responses. May change when the field is renamed. |
| description | string / null | yes | Free-text note about the field, or null when none was set. |
| required | boolean | yes | Whether every row must hold a non-null value for this field. |
| unique | boolean | yes | Whether values must be distinct across rows; fixed at creation. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| indexed | boolean | yes | Whether an index is maintained for faster filters and ordering. Always false for json and link fields. |
| type | "string" / "integer" / "number" / "boolean" / "datetime" | yes | Scalar data type of the field; it cannot be changed after the field is created. |
| options | object | no | Scalar fields take no options; always an empty object. |
| default | JSON | no | Default JSON value for omitted insert fields; must match the field type and JSON schema. A datetime default of "now()" evaluates to server time on insertion and reads back as "now()" in the field definition. For string and json fields it is a literal string. Explicit null remains null. Link fields do not support defaults. |
"json"
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | yes | Field identifier, prefixed fld_. Stable across renames; accepted wherever a field path parameter takes an id or name. |
| name | string | yes | Current field name; rows are keyed by it in requests and responses. May change when the field is renamed. |
| description | string / null | yes | Free-text note about the field, or null when none was set. |
| required | boolean | yes | Whether every row must hold a non-null value for this field. |
| unique | boolean | yes | Whether values must be distinct across rows; fixed at creation. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| indexed | boolean | yes | Whether an index is maintained for faster filters and ordering. Always false for json and link fields. |
| type | "json" | yes | Type json: the value is any JSON document validated against options.schema. It cannot be changed after the field is created. |
| options | object | yes | Settings of a json field. schema is required. |
| default | JSON | no | Default JSON value for omitted insert fields; must match the field type and JSON schema. A datetime default of "now()" evaluates to server time on insertion and reads back as "now()" in the field definition. For string and json fields it is a literal string. Explicit null remains null. Link fields do not support defaults. |
"link"
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | yes | Field identifier, prefixed fld_. Stable across renames; accepted wherever a field path parameter takes an id or name. |
| name | string | yes | Current field name; rows are keyed by it in requests and responses. May change when the field is renamed. |
| description | string / null | yes | Free-text note about the field, or null when none was set. |
| required | boolean | yes | Whether every row must hold a non-null value for this field. |
| unique | boolean | yes | Whether values must be distinct across rows; fixed at creation. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| indexed | boolean | yes | Whether an index is maintained for faster filters and ordering. Always false for json and link fields. |
| type | "link" | yes | Type link: the value is the id of a row in another table (an array of ids when options.multiple is true). It cannot be changed after the field is created. |
| options | object | yes | Settings of a link field. Both linked_table_id and multiple are required. |
"string" / "integer" / "number" / "boolean" / "datetime"
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Field name. Only id is reserved; new field names cannot start with _ (reserved for system metadata). created_at, updated_at and version are ordinary user field names. Existing underscore-prefixed fields remain usable and take precedence over metadata.; ^(?!id$)[a-z][a-z0-9_]{0,62}$ |
| description | string | no | Optional free-text note about the field; omit it to store null. |
| required | boolean | no | Whether every row must hold a non-null value for this field. Defaults to false. |
| unique | boolean | no | Whether values must be distinct across rows. Defaults to false; cannot be changed after the field exists. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| indexed | boolean | no | Whether to maintain an index for faster filters and ordering. Defaults to true for scalar types and is not allowed for json and link fields. At most 16 indexed or unique fields per table. |
| type | "string" / "integer" / "number" / "boolean" / "datetime" | yes | Scalar data type of the field; it cannot be changed after the field is created. |
| options | object | no | Scalar fields take no options; always an empty object. |
| default | JSON | no | Default JSON value for omitted insert fields; must match the field type and JSON schema. A datetime default of "now()" evaluates to server time on insertion and reads back as "now()" in the field definition. For string and json fields it is a literal string. Explicit null remains null. Link fields do not support defaults. |
"json"
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Field name. Only id is reserved; new field names cannot start with _ (reserved for system metadata). created_at, updated_at and version are ordinary user field names. Existing underscore-prefixed fields remain usable and take precedence over metadata.; ^(?!id$)[a-z][a-z0-9_]{0,62}$ |
| description | string | no | Optional free-text note about the field; omit it to store null. |
| required | boolean | no | Whether every row must hold a non-null value for this field. Defaults to false. |
| unique | boolean | no | Whether values must be distinct across rows. Defaults to false; cannot be changed after the field exists. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| indexed | boolean | no | Whether to maintain an index for faster filters and ordering. Defaults to true for scalar types and is not allowed for json and link fields. At most 16 indexed or unique fields per table. |
| type | "json" | yes | Type json: the value is any JSON document validated against options.schema. It cannot be changed after the field is created. |
| options | object | yes | Settings of a json field. schema is required. |
| default | JSON | no | Default JSON value for omitted insert fields; must match the field type and JSON schema. A datetime default of "now()" evaluates to server time on insertion and reads back as "now()" in the field definition. For string and json fields it is a literal string. Explicit null remains null. Link fields do not support defaults. |
"link"
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Field name. Only id is reserved; new field names cannot start with _ (reserved for system metadata). created_at, updated_at and version are ordinary user field names. Existing underscore-prefixed fields remain usable and take precedence over metadata.; ^(?!id$)[a-z][a-z0-9_]{0,62}$ |
| description | string | no | Optional free-text note about the field; omit it to store null. |
| required | boolean | no | Whether every row must hold a non-null value for this field. Defaults to false. |
| unique | boolean | no | Whether values must be distinct across rows. Defaults to false; cannot be changed after the field exists. A unique field is indexed, and a violation returns 409 UNIQUE_VIOLATION. |
| indexed | boolean | no | Whether to maintain an index for faster filters and ordering. Defaults to true for scalar types and is not allowed for json and link fields. At most 16 indexed or unique fields per table. |
| type | "link" | yes | Type link: the value is the id of a row in another table (an array of ids when options.multiple is true). It cannot be changed after the field is created. |
| options | object | yes | Settings of a link field. Both linked_table_id and multiple are required. |
Events record database lifecycle and table/field changes, not row reads or writes.
Defaults to ascending seq; before_seq alone implies desc (newest first). next_cursor is an opaque string cursor — pass it back unchanged, as after_seq for asc or before_seq for desc. Both cursors together, or before_seq with order=asc, return 400 INVALID_PARAMS. Events remain readable while a database is deleting.
next_cursor is an opaque string cursor: pass it back unchanged and do not do arithmetic on it. A null next_cursor means there is no next page. The captured response below uses the default ascending order. Descending pagination uses the requests below; live responses for this extension will be added after the service update.
# Newest page
curl "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/events?order=desc&limit=10" \
-H "Authorization: Bearer $PRAXIS_API_KEY"
# Set NEXT_CURSOR to the previous response's next_cursor
curl "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/events?order=desc&before_seq=${NEXT_CURSOR}&limit=10" \
-H "Authorization: Bearer $PRAXIS_API_KEY"GET /database/v1/databases/{database_id}/events
| Parameter | Location | Description |
|---|---|---|
| database_id | path | Identifier of the database to act on: the id (db_…) returned by databaseCreateDatabase or databaseListDatabases. A display name is not accepted. |
| after_seq | query | With order=asc, return only events with seq greater than this value. Cannot be combined with before_seq. |
| limit | query | Page size. (default: 50) (1–200) |
| order | query | Sequence order: asc or desc (newest first). Defaults to asc, or to desc when before_seq is supplied. |
| before_seq | query | Return only events with seq less than this value, newest first; implies order=desc when order is omitted. Cannot be combined with after_seq or order=asc. |
Returns: Page + object.
Success
application/json
| Name | Type | Description |
|---|---|---|
| data | array<object> | Events on this page in the requested order (ascending seq by default, newest first with before_seq or order=desc). |
| data[].seq | integer | Position of the event in the database's event log; starts at 1 and strictly increases. Use it as after_seq or before_seq to page. |
| data[].id | string | Unique identifier of this event record. |
| data[].type | string | What happened: a lifecycle transition of the database, or a schema change to a table or field. |
| data[].processed_at | string | Time the event was recorded, as an RFC 3339 UTC timestamp. |
| data[].database_id | string | Id (db_…) of the database the event belongs to. |
| data[].table_id | string | Id (tbl_…) of the affected table; present only for table and field events. |
| data[].field_id | string | Id (fld_…) of the affected field; present only for field events. |
| next_cursor | string | null | Opaque cursor for the next page, or null when there are no more items. Databases list: pass it as cursor. Events list: pass it as after_seq (order asc) or before_seq (order desc). |
curl -X GET "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/events?after_seq=0&limit=10" \
-H "Authorization: Bearer $PRAXIS_API_KEY"Response example — HTTP 200
{
"data": [
{
"seq": 1,
"id": "7390d75e-216c-4799-891e-c043bac8bce5",
"type": "database.status_provisioning",
"processed_at": "2026-10-11T17:41:41.339Z",
"database_id": "db_d6f0d743d5a645e8"
},
{
"seq": 2,
"id": "39db0ef4-99b4-4846-9d50-9998e25cf48f",
"type": "database.status_active",
"processed_at": "2026-10-11T17:41:41.339Z",
"database_id": "db_d6f0d743d5a645e8"
},
{
"seq": 3,
"id": "d295651d-5e83-4b42-bcd3-c979fb71f375",
"type": "table.created",
"processed_at": "2026-10-11T17:41:44.246Z",
"database_id": "db_d6f0d743d5a645e8",
"table_id": "tbl_2b3431c772754599"
},
{
"seq": 4,
"id": "eb255753-3dd7-4eae-8861-d53408bfcaf4",
"type": "table.updated",
"processed_at": "2026-10-11T17:41:45.127Z",
"database_id": "db_d6f0d743d5a645e8",
"table_id": "tbl_2b3431c772754599"
},
{
"seq": 5,
"id": "99c86e22-0629-4391-85e5-d7b8b31de833",
"type": "field.added",
"processed_at": "2026-10-11T17:41:45.420Z",
"database_id": "db_d6f0d743d5a645e8",
"table_id": "tbl_2b3431c772754599",
"field_id": "fld_4c3e63869e35458c"
},
{
"seq": 6,
"id": "a9b85950-363d-4ab3-8c85-6228eec3d099",
"type": "field.updated",
"processed_at": "2026-10-11T17:41:46.276Z",
"database_id": "db_d6f0d743d5a645e8",
"table_id": "tbl_2b3431c772754599",
"field_id": "fld_4c3e63869e35458c"
},
{
"seq": 7,
"id": "73ca124f-6cbb-4a43-8a37-4ff50a211dd5",
"type": "field.deleted",
"processed_at": "2026-10-11T17:41:47.136Z",
"database_id": "db_d6f0d743d5a645e8",
"table_id": "tbl_2b3431c772754599",
"field_id": "fld_4c3e63869e35458c"
}
],
"next_cursor": null
}| Field | Type | Required | Description |
|---|---|---|---|
| seq | integer | yes | Position of the event in the database's event log; starts at 1 and strictly increases. Use it as after_seq or before_seq to page. |
| id | string | yes | Unique identifier of this event record. |
| type | "database.status_provisioning" / "database.status_active" / "database.status_deleting" / "database.status_deleted" / "database.status_failed" / "database.restored" / "table.created" / "table.updated" / "table.deleted" / "field.added" / "field.updated" / "field.deleted" | yes | What happened: a lifecycle transition of the database, or a schema change to a table or field. |
| processed_at | date-time | yes | Time the event was recorded, as an RFC 3339 UTC timestamp. |
| database_id | string | yes | Id (db_…) of the database the event belongs to. |
| table_id | string | no | Id (tbl_…) of the affected table; present only for table and field events. |
| field_id | string | no | Id (fld_…) of the affected field; present only for field events. |
/database/v1/databases/{database_id}/rest/{table}
Reads and writes the same rows as the other entry point for this database. Errors use PostgREST codes.
Support matrix and client setup
Full parameters, response headers and status codes
One batch POST inserts at most 500 rows. Each request is atomic: a failure in any row rolls back the entire batch. There are no transactions across requests. Put rows that must succeed together in one batch POST. For links, query first, then insert, and handle link errors caused by concurrent changes.
Rows in a batch are filled to the union of their keys with null (PostgREST behavior). Send Prefer: missing=default to use field defaults instead. Explicit null remains null; required fields without defaults must still be provided. The default return=minimal returns 201 with an empty body; send Prefer: return=representation to return rows.
GET /database/v1/databases/{database_id}/rest/{table}
curl -X GET "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/rest/tasks?select=*&order=title.asc&limit=10" \
-H "Authorization: Bearer $PRAXIS_API_KEY"Success; write bodies require Prefer: return=representation
application/json
| Name | Type | Description |
|---|---|---|
| [].id | string | Row identifier of 1–64 characters from A-Z a-z 0-9 _ -. Generated by the service unless the insert supplied one; it cannot be changed by updates. |
application/vnd.pgrst.object+json
| Name | Type | Description |
|---|---|---|
| id | string | Row identifier of 1–64 characters from A-Z a-z 0-9 _ -. Generated by the service unless the insert supplied one; it cannot be changed by updates. |
Partial range with requested count
application/json
| Name | Type | Description |
|---|---|---|
| [].id | string | Row identifier of 1–64 characters from A-Z a-z 0-9 _ -. Generated by the service unless the insert supplied one; it cannot be changed by updates. |
application/vnd.pgrst.object+json
| Name | Type | Description |
|---|---|---|
| id | string | Row identifier of 1–64 characters from A-Z a-z 0-9 _ -. Generated by the service unless the insert supplied one; it cannot be changed by updates. |
Response example — HTTP 200
| Header | Value |
|---|---|
| content-range | 0-0/* |
| etag | W/"5.1" |
| range-unit | items |
[
{
"id": "rec_3e85a292099340e3",
"version": 1,
"created_at": "2026-10-11T17:41:47.896Z",
"updated_at": "2026-10-11T17:41:47.896Z",
"title": "Write a summary",
"done": false
}
]HEAD /database/v1/databases/{database_id}/rest/{table}
curl --head "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/rest/tasks?select=*" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H 'prefer: count=exact'Success; write bodies require Prefer: return=representation
No response body is declared.
Partial range with requested count
No response body is declared.
Response example — HTTP 200
| Header | Value |
|---|---|
| content-range | 0-0/1 |
| preference-applied | count=exact |
| etag | W/"5.1" |
| range-unit | items |
No response body.
POST /database/v1/databases/{database_id}/rest/{table}
curl -X POST "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/rest/tasks" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H 'prefer: return=representation' \
-H "Content-Type: application/json" \
-d '{"title":"Write a summary","done":false}'Success (201). With the default return=minimal the body is empty; Prefer: return=representation returns rows.
application/json
| Name | Type | Description |
|---|---|---|
| [].id | string | Row identifier of 1–64 characters from A-Z a-z 0-9 _ -. Generated by the service unless the insert supplied one; it cannot be changed by updates. |
application/vnd.pgrst.object+json
| Name | Type | Description |
|---|---|---|
| id | string | Row identifier of 1–64 characters from A-Z a-z 0-9 _ -. Generated by the service unless the insert supplied one; it cannot be changed by updates. |
Response example — HTTP 201
| Header | Value |
|---|---|
| content-range | 0-0/* |
| preference-applied | return=representation |
| range-unit | items |
[
{
"id": "rec_3e85a292099340e3",
"version": 1,
"created_at": "2026-10-11T17:41:47.896Z",
"updated_at": "2026-10-11T17:41:47.896Z",
"title": "Write a summary",
"done": false
}
]PATCH /database/v1/databases/{database_id}/rest/{table}
curl -X PATCH "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/rest/tasks?title=eq.Write%20a%20summary" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H 'prefer: return=representation' \
-H "Content-Type: application/json" \
-d '{"done":true}'Success; write bodies require Prefer: return=representation
application/json
| Name | Type | Description |
|---|---|---|
| [].id | string | Row identifier of 1–64 characters from A-Z a-z 0-9 _ -. Generated by the service unless the insert supplied one; it cannot be changed by updates. |
application/vnd.pgrst.object+json
| Name | Type | Description |
|---|---|---|
| id | string | Row identifier of 1–64 characters from A-Z a-z 0-9 _ -. Generated by the service unless the insert supplied one; it cannot be changed by updates. |
Success without a body
No response body is declared.
Response example — HTTP 200
| Header | Value |
|---|---|
| content-range | 0-0/* |
| preference-applied | return=representation |
| range-unit | items |
[
{
"id": "rec_3e85a292099340e3",
"version": 2,
"created_at": "2026-10-11T17:41:47.896Z",
"updated_at": "2026-10-11T17:41:48.802Z",
"title": "Write a summary",
"done": true
}
]POST /database/v1/databases/{database_id}/rest/{table}
curl -X POST "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/rest/tasks?on_conflict=title" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H 'prefer: resolution=merge-duplicates,return=representation' \
-H "Content-Type: application/json" \
-d '{"title":"Write a summary","done":true}'Success (201). With the default return=minimal the body is empty; Prefer: return=representation returns rows.
application/json
| Name | Type | Description |
|---|---|---|
| [].id | string | Row identifier of 1–64 characters from A-Z a-z 0-9 _ -. Generated by the service unless the insert supplied one; it cannot be changed by updates. |
application/vnd.pgrst.object+json
| Name | Type | Description |
|---|---|---|
| id | string | Row identifier of 1–64 characters from A-Z a-z 0-9 _ -. Generated by the service unless the insert supplied one; it cannot be changed by updates. |
Response example — HTTP 201
| Header | Value |
|---|---|
| content-range | 0-0/* |
| preference-applied | resolution=merge-duplicates, return=representation |
| range-unit | items |
[
{
"id": "rec_3e85a292099340e3",
"version": 3,
"created_at": "2026-10-11T17:41:47.896Z",
"updated_at": "2026-10-11T17:41:49.076Z",
"title": "Write a summary",
"done": true
}
]DELETE /database/v1/databases/{database_id}/rest/{table}
curl -X DELETE "https://api.deepraxis.ai/database/v1/databases/${DATABASE_ID}/rest/tasks?title=eq.Write%20a%20summary" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H 'prefer: return=representation'Success; write bodies require Prefer: return=representation
application/json
| Name | Type | Description |
|---|---|---|
| [].id | string | Row identifier of 1–64 characters from A-Z a-z 0-9 _ -. Generated by the service unless the insert supplied one; it cannot be changed by updates. |
application/vnd.pgrst.object+json
| Name | Type | Description |
|---|---|---|
| id | string | Row identifier of 1–64 characters from A-Z a-z 0-9 _ -. Generated by the service unless the insert supplied one; it cannot be changed by updates. |
Success without a body
No response body is declared.
Response example — HTTP 200
| Header | Value |
|---|---|
| content-range | 0-0/* |
| preference-applied | return=representation |
| range-unit | items |
[
{
"id": "rec_3e85a292099340e3",
"version": 3,
"created_at": "2026-10-11T17:41:47.896Z",
"updated_at": "2026-10-11T17:41:49.076Z",
"title": "Write a summary",
"done": true
}
]Default projections, select=, return=representation and RPC row objects return only id and user fields. Explicitly request metadata with select=,_version,_created_at,_updated_at; star does not expand it. Filter with _version=eq.3 or sort with order=_created_at.desc. Metadata is read-only. Default order remains internal creation time then id. Old filter/order names created_at/updated_at/version without same-named user fields return 400, details use _created_at (or the corresponding name), and hint system metadata moved to underscore columns. Existing underscore user fields take precedence; their same-named system metadata is inaccessible in that table. Historical response examples above were captured before this change and may still contain old metadata columns; this section defines the current row shape.
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | yes | Row identifier of 1–64 characters from A-Z a-z 0-9 _ -. Generated by the service unless the insert supplied one; it cannot be changed by updates.; ^[A-Za-z0-9_-]{1,64}$ |
Management endpoints return domain codes; both table endpoints return PostgREST codes. HTTP status and retryability are listed below.
| Domain code | HTTP | PostgREST code | Retryable |
|---|---|---|---|
| SINGULAR_MISMATCH | 406 | PGRST116 | no |
| AMBIGUOUS_EMBED | 300 | PGRST201 | no |
| EMBED_NOT_FOUND | 400 | PGRST200 | no |
| INVALID_PREFERENCE | 400 | PGRST122 | no |
| QUERY_CANCELED | 500 | 57014 | no |
| RANGE_NOT_SATISFIABLE | 416 | PGRST103 | no |
| NOT_ACCEPTABLE | 406 | PGRST107 | no |
| OPERATOR_TYPE_MISMATCH | 400 | 42883 | no |
| DATABASE_NOT_FOUND | 404 | PGRST125 | no |
| TABLE_NOT_FOUND | 404 | PGRST205 | no |
| FIELD_NOT_FOUND | 400 | 42703 | no |
| VALIDATION_FAILED | 400 | 23514 | no |
| UNIQUE_VIOLATION | 409 | 23505 | no |
| REFERENCE_RESTRICT | 409 | 23503 | no |
| FIELD_TYPE_IMMUTABLE | 400 | — | no |
| LIMIT_EXCEEDED | 400 | 54000 | no |
| UNSUPPORTED | 400 | PGRST127 | no |
| INVALID_PARAMS | 400 | PGRST100 | no |
| DATABASE_INVALID_STATE | 409 | — | no |
| CAPACITY | 503 | — | yes |
| NOT_IMPLEMENTED | 501 | PGRST127 | no |
Retryable does not mean repeating the same request will succeed. For 57014, narrow the query or change its filters before retrying.
Response example — HTTP 400
{
"code": "FIELD_TYPE_IMMUTABLE",
"message": "field type is immutable",
"details": null,
"hint": null
}Response example — HTTP 400
{
"code": "PGRST127",
"message": "operator fts is not supported",
"details": null,
"hint": null
}The code, message, details and hint fields are always present; details and hint can be null.
Response example — HTTP 501
| Header | Value |
|---|---|
| x-should-retry | false |
{
"code": "not_implemented",
"message": "auth is not provided by praxis-database"
}These five services return not_implemented directly; this differs from the NOT_IMPLEMENTED domain code in the table.
Only id is a reserved field name. New field names cannot start with _, which is reserved for system metadata. created_at, updated_at and version are ordinary user field names. Datetime fields can use "now()" as a default.
details identifies the field or JSON path and the received value. Batch validation includes a zero-based row index. Values are limited to 80 characters; the entire row is never echoed. hint suggests a correction, or is null when no suggestion applies. This example omits the required title in row 2:
{
"code": "23514",
"message": "row validation failed",
"details": "row 1: title: required value (got null)",
"hint": "Rows in one insert are filled to the union of their keys with null (PostgREST behavior). Send every key in every row, or send Prefer: missing=default to use field defaults."
}A unique conflict returns 409, for example:
{
"code": "23505",
"message": "unique constraint violated",
"details": "Key (email)=(a@b.c) already exists.",
"hint": null
}