Serenities AI™
Back to API Overview

Base & Tables API

Manage bases, tables, fields, and records. This router provides full CRUD operations for your database infrastructure.

47 endpoints

Endpoints

POST
/api/v1/tables/createDatabase

Create a new database (base). Returns the created database with its ID.

Parameters

namestringrequired

Name for the new database/base

descriptionstring

Optional description of the database

iconstring

Icon name (e.g., "database", "folder")

colorstring

Hex color code (e.g., "#3B82F6")

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/createDatabase \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "example",
  "description": "example",
  "icon": "example"
}'
POST
/api/v1/tables/listDatabases

List all databases (bases) for the current user. Returns array with id, name, description, tables[]. Use this first to get database IDs.

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/listDatabases \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{}'
POST
/api/v1/tables/getDatabaseById

Get a specific database with its tables

Parameters

idstringrequired

Database ID from listDatabases

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/getDatabaseById \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "example"
}'
POST
/api/v1/tables/updateDatabase

Update database properties. Only provided fields are updated.

Parameters

idstringrequired

Database ID from listDatabases

namestring

New name for the database

descriptionstring

New description

iconstring

New icon name

colorstring

New hex color code

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/updateDatabase \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "example",
  "name": "example",
  "description": "example"
}'
POST
/api/v1/tables/deleteDatabase

Permanently delete a database and all its contents

Parameters

idstringrequired

Database ID to delete. WARNING: This permanently deletes all tables and data.

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/deleteDatabase \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "example"
}'
POST
/api/v1/tables/createTable

Create a new table in a database. Returns the created table.

Parameters

databaseIdstringrequired

Database ID from listDatabases where the table will be created

namestringrequired

Name for the new table

descriptionstring

Optional description of the table

iconstring

Icon name (e.g., "table", "users")

colorstring

Hex color code (e.g., "#10B981")

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/createTable \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "databaseId": "example",
  "name": "example",
  "description": "example"
}'
POST
/api/v1/tables/listTables

List all tables across all databases. Returns array with id, name, databaseId. Use getTableById for full details.

Parameters

databaseIdstring

Limit to one base — omit for all tables across all bases

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/listTables \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "databaseId": "example"
}'
POST
/api/v1/tables/getViewsByTableId

Get all views for a table

Parameters

tableIdstringrequired

Table ID from listTables

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/getViewsByTableId \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example"
}'
POST
/api/v1/tables/getFieldsByTableId

Get all fields/columns for a table. Returns field IDs needed for createRow data keys.

Parameters

tableIdstringrequired

Table ID from listTables

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/getFieldsByTableId \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example"
}'
POST
/api/v1/tables/getTableById

Get table with fields and views. Returns field IDs needed for row data.

Parameters

idstringrequired

Table ID from listTables

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/getTableById \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "example"
}'
POST
/api/v1/tables/updateTable

Update table properties. Only provided fields are updated.

Parameters

idstringrequired

Table ID from listTables

namestring

New name for the table

descriptionstring

New description

iconstring

New icon name

colorstring

New hex color code

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/updateTable \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "example",
  "name": "example",
  "description": "example"
}'
POST
/api/v1/tables/deleteTable

Permanently delete a table and all its data

Parameters

idstringrequired

Table ID to delete. WARNING: This permanently deletes all rows and fields.

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/deleteTable \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "example"
}'
POST
/api/v1/tables/createField

Create a new field/column in a table

Parameters

tableIdstringrequired

Table ID from listTables

namestringrequired

Name for the new field/column

fieldTypestringrequired

Field type: "text", "number", "select", "multiselect", "date", "datetime", "checkbox", "url", "email", "phone", "file", "formula", "rating", "currency", "percent", "duration", "status", "button", "link", "lookup", "rollup". READ-ONLY computed types (writes to them are dropped): "hash" = Hash ID, a read-only stable per-row identifier — it does NOT hash a value you supply (to store a hashed value, compute it yourself and use text/secret); "created_time"/"updated_time" = system timestamps; "formula"/"lookup"/"rollup" = computed. Numbers are exact only up to 2^53 — unsafe integers are rejected with guidance; store long IDs, account numbers, and IMEIs as text.

descriptionstring

Optional description of the field

requiredboolean

Must be false or omitted. Required fields are not supported - UI creates blank rows first.

uniqueboolean

Whether values must be unique (default: false)

defaultValueany

Default value for new rows

optionsarray

For select/multiselect: [{value: "opt1", label: "Option 1", color: "#3b82f6"}]

statusLabelsarray

For status: [{value: "todo", label: "To Do", color: "#6b7280"}]

formulaConfigobject

For formula: {formula: "{Field A} * {Field B}", resultType: text|number|date|checkbox}. Non-volatile formula values are materialized (stored on the row, auto-recalculated when inputs change — including via links) and are filterable/queryable everywhere; formulas using NOW()/TODAY() are volatile: display-only, empty when filtering or sorting, not filterable

buttonConfigobject

For button: {actionType: "flow", flowId: "xxx"}

numberFormatConfigobject

For number: {decimalPlaces: 2, useThousandSeparator: true}

currencyFormatConfigobject

For currency: {currencySymbol: "$", symbolPosition: "before"}

percentFormatConfigobject

For percent: {decimalPlaces: 1}

lookupConfigobject

For lookup: {relationshipFieldId: "<link field id>", sourceFieldId: "<field id on linked table>", aggregation?: CONCATENATE|FIRST|LAST|ARRAY|COUNT|SUM|AVG|MIN|MAX (default CONCATENATE; COUNT counts NON-EMPTY VALUES — use a rollup COUNT to count linked records), filter?: {logic, conditions:[{fieldId,operator,value}]} over LINKED-table fields — only matching linked rows are aggregated}. Computed by Postgres; scalar (non-chained) aggregations are filterable everywhere — view filters, filterRows, and published-app entities.filter()

rollupConfigobject

For rollup: {relationshipFieldId: "<link field id>", sourceFieldId: "<field id on linked table>", aggregation: COUNT|COUNT_EMPTY|COUNT_FILLED|COUNT_UNIQUE|SUM|AVG|MIN|MAX|MEDIAN|CONCATENATE|ARRAY|ARRAY_UNIQUE|ARRAY_COMPACT (default COUNT; COUNT counts LINKED RECORDS incl. empty values — COUNT_FILLED matches lookup COUNT), filter?: {logic, conditions:[{fieldId,operator,value}]} over LINKED-table fields — only matching linked rows are aggregated}. Computed by Postgres; scalar (non-chained) aggregations are filterable everywhere — view filters, filterRows, and published-app entities.filter()

linkedTableIdstring

For link field: target table ID

linkTypestring

Link relationship type

displayOrderstring

Fractional order string (e.g., "a0", "b0")

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/createField \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "name": "example",
  "fieldType": "example"
}'
POST
/api/v1/tables/updateField

Update field properties. Only provided fields are updated.

Parameters

idstringrequired

Field ID from getFieldsByTableId

namestring

New name for the field

fieldTypestring

Field type

descriptionstring

New description

requiredboolean

Must be false or omitted. Required fields are not supported - UI creates blank rows first.

uniqueboolean

Whether values must be unique

defaultValueany

Default value for new rows

optionsarray

For select/multiselect: [{value: "opt1", label: "Option 1", color: "#3b82f6"}]

statusLabelsarray

For status: [{value: "todo", label: "To Do", color: "#6b7280"}]

formulaConfigobject

For formula: {formula: "{Field A} * {Field B}", resultType: text|number|date|checkbox}. Non-volatile formula values are materialized (stored on the row, auto-recalculated when inputs change — including via links) and are filterable/queryable everywhere; formulas using NOW()/TODAY() are volatile: display-only, empty when filtering or sorting, not filterable

linkedTableIdstring

For link field: target table ID

linkTypestring

Link relationship type

linkDisplayModestring

How to display linked records

linkDisplayFieldIdstring

Which field to show from linked records

allowMultipleLinksboolean

Whether multiple links are allowed

linkOnDeletestring

For link fields: what happens to linking rows when a linked record is deleted. RESTRICT blocks the delete; CASCADE deletes the linking rows too (chains, capped at 500 rows per delete); SET_NULL (default) just removes the connection.

buttonConfigobject

For button: {actionType: "flow", flowId: "xxx"}

numberFormatConfigobject

For number: {decimalPlaces: 2, useThousandSeparator: true}

currencyFormatConfigobject

For currency: {currencySymbol: "$", symbolPosition: "before"}

percentFormatConfigobject

For percent: {decimalPlaces: 1}

lookupConfigobject

For lookup: {relationshipFieldId: "<link field id>", sourceFieldId: "<field id on linked table>", aggregation?: CONCATENATE|FIRST|LAST|ARRAY|COUNT|SUM|AVG|MIN|MAX (default CONCATENATE; COUNT counts NON-EMPTY VALUES — use a rollup COUNT to count linked records), filter?: {logic, conditions:[{fieldId,operator,value}]} over LINKED-table fields — only matching linked rows are aggregated}. Computed by Postgres; scalar (non-chained) aggregations are filterable everywhere — view filters, filterRows, and published-app entities.filter()

rollupConfigobject

For rollup: {relationshipFieldId: "<link field id>", sourceFieldId: "<field id on linked table>", aggregation: COUNT|COUNT_EMPTY|COUNT_FILLED|COUNT_UNIQUE|SUM|AVG|MIN|MAX|MEDIAN|CONCATENATE|ARRAY|ARRAY_UNIQUE|ARRAY_COMPACT (default COUNT; COUNT counts LINKED RECORDS incl. empty values — COUNT_FILLED matches lookup COUNT), filter?: {logic, conditions:[{fieldId,operator,value}]} over LINKED-table fields — only matching linked rows are aggregated}. Computed by Postgres; scalar (non-chained) aggregations are filterable everywhere — view filters, filterRows, and published-app entities.filter()

displayOrdernumber

Display order position

isVisibleboolean

Whether field is visible

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/updateField \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "example",
  "name": "example",
  "fieldType": "example"
}'
POST
/api/v1/tables/deleteField

Permanently delete a field/column and all its data

Parameters

idstringrequired

Field ID to delete. WARNING: This permanently deletes all data in this column.

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/deleteField \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "example"
}'
POST
/api/v1/tables/createRow

Create a new row in a table. Data keys must be field IDs, not field names.

Parameters

tableIdstringrequired

Table ID from listTables

dataobjectrequired

Object where keys are FIELD IDs from getFieldsByTableId, values are cell values. Example: {"fieldId1": "text", "fieldId2": 123}

rowOrderstring

Fractional order string for positioning. Leave empty to append at end.

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/createRow \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "data": {},
  "rowOrder": "example"
}'
POST
/api/v1/tables/report

Answer a numbers question about a table: counts, totals, averages per slice

Parameters

filterany

Which rows count: {logic: "and"|"or", conditions: [{fieldId, operator, value}]} — the view filter language

groupByarray

Up to 3 slices

measuresarrayrequired

1 to 8 numbers to work out per slice

havingarray

Keep only slices whose measure passes (up to 4)

sortarray

Order by group or measure names (up to 3)

limitinteger

Slices per answer, 1-1000 (default 100)

offsetinteger

Slices to skip, for the next page (max 100000)

percentOfTotalstring

The `as` of a count or sum measure: adds each slice's share of the whole (0-1)

timeZonestring

IANA time zone for date slices, e.g. "Europe/Berlin" (default UTC)

tableIdstringrequired

Table ID from listTables

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/report \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "filter": {},
  "groupBy": {},
  "measures": {}
}'
POST
/api/v1/tables/getRowCount

Get total row count for a table. Lightweight operation.

Parameters

tableIdstringrequired

Table ID from listTables

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/getRowCount \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example"
}'
POST
/api/v1/tables/getRows

Get rows from a table with pagination. Returns row data with field IDs as keys.

Parameters

tableIdstringrequired

Table ID from listTables

limitnumber

Rows to return, 1-1000 (default: 100). Values outside the range are REJECTED, not clamped — page with offset for more

offsetnumber

Number of rows to skip for pagination

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/getRows \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "limit": 0,
  "offset": 0
}'
POST
/api/v1/tables/updateRow

Update an existing row. Merges provided data with existing data.

Parameters

idstringrequired

Row ID from getRows

dataobjectrequired

Object with field IDs as keys and new values. Only provided fields are updated.

metadataobject

Optional metadata to merge with existing

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/updateRow \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "example",
  "data": {},
  "metadata": {}
}'
POST
/api/v1/tables/restoreRow

Undo a row delete: bring back a row this same person deleted (with deleteRow or bulkDeleteRows) in the last ten minutes, at its old id, exactly as it was (its values are the copy kept when it was deleted). Params: tableId, rowId (the deleted row's id), rowOrder? (a row position the grid made, e.g. one taken from getRows; anything else is refused; default: where it was). Each delete can be undone once. A row deleted by someone else, longer ago, or never deleted answers "Row not found". Returns { id, tableId, data, rowOrder, createdAt, updatedAt } (secret values masked).

Parameters

tableIdstringrequired

The table the row was deleted from

rowIdstringrequired

The deleted row's id

rowOrderstring

Where to put it back (a row position the grid made; a bad one is refused); default: where it was

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/restoreRow \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "rowId": "example",
  "rowOrder": "example"
}'
POST
/api/v1/tables/deleteRow

Permanently delete a single row

Parameters

idstringrequired

Row ID to delete

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/deleteRow \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "example"
}'
POST
/api/v1/tables/bulkDeleteRows

Delete multiple rows. Params: tableId, rowIds (array of row IDs).

Parameters

tableIdstringrequired
rowIdsarrayrequired

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/bulkDeleteRows \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "rowIds": {}
}'
POST
/api/v1/tables/createView

Create a new view. Params: tableId (required), name (required), viewType (required: "grid", "kanban", "calendar", "gallery", "form"), description, filterConfig, sortConfig, groupConfig, visibleFields (array of field IDs).

Parameters

tableIdstringrequired
namestringrequired
viewTypestringrequired
descriptionstring
filterConfigany
sortConfigany
groupConfigany
visibleFieldsarray
columnWidthsany
isDefaultboolean

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/createView \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "name": "example",
  "viewType": "example"
}'
POST
/api/v1/tables/updateView

Update view settings. Params: id (view ID), name, filterConfig, sortConfig, groupConfig, visibleFields, etc.

Parameters

idstringrequired
namestring
descriptionstring
filterConfigany
sortConfigany
groupConfigany
visibleFieldsarray
columnWidthsany
isDefaultboolean
metadataany

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/updateView \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "example",
  "name": "example",
  "description": "example"
}'
POST
/api/v1/tables/getViews

List all views for a table. Param "tableId". Returns array with id, name, viewType, filterConfig, sortConfig.

Parameters

tableIdstringrequired

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/getViews \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example"
}'
POST
/api/v1/tables/reorderView

Change view position. Params: viewId, newOrderIndex (string).

Parameters

viewIdstringrequired
newOrderIndexstringrequired

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/reorderView \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "viewId": "example",
  "newOrderIndex": "example"
}'
POST
/api/v1/tables/duplicateView

Copy a view. Params: id (view ID to copy), name (optional, for the copy).

Parameters

idstringrequired
namestring

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/duplicateView \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "example",
  "name": "example"
}'
POST
/api/v1/tables/setDefaultView

Set which view opens by default. Params: id (view ID), tableId.

Parameters

idstringrequired
tableIdstringrequired

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/setDefaultView \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "example",
  "tableId": "example"
}'
POST
/api/v1/tables/deleteView

Delete a view. Param "id" is the view ID.

Parameters

idstringrequired

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/deleteView \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "example"
}'
POST
/api/v1/tables/updateFieldOrder

Change field position. Params: fieldId, newOrder (fractional string).

Parameters

fieldIdstringrequired
newOrderstringrequired

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/updateFieldOrder \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "fieldId": "example",
  "newOrder": "example"
}'
POST
/api/v1/tables/updateTableOrder

Change table position in database. Params: tableId, newOrder (string like "a0", "b0" for fractional ordering).

Parameters

tableIdstringrequired
newOrderstringrequired

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/updateTableOrder \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "newOrder": "example"
}'
POST
/api/v1/tables/updateFieldWidth

Set column width in pixels. Params: fieldId, width (number, e.g., 200).

Parameters

fieldIdstringrequired
widthnumberrequired

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/updateFieldWidth \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "fieldId": "example",
  "width": 0
}'
POST
/api/v1/tables/updateRowOrder

Update row display order for row drag-and-drop

Parameters

rowIdstringrequired

Row ID to reorder

newOrderstringrequired

New fractional order string

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/updateRowOrder \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "rowId": "example",
  "newOrder": "example"
}'
POST
/api/v1/tables/bulkUpdateRows

Update multiple rows at once. Each update merges its data with the existing row data — like updateRow but batched.

Parameters

tableIdstringrequired

Table ID from listTables

updatesarrayrequired

Array of row updates

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/bulkUpdateRows \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "updates": {}
}'
POST
/api/v1/tables/exportTable

Export all table data for download

Parameters

tableIdstringrequired

Table ID to export

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/exportTable \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example"
}'
POST
/api/v1/tables/importRows

Bulk import rows. Use matchFieldsByName=true (default) to use field names as keys. Send about 5,000 rows a call, fewer for a wide table: a call takes at most 100,000 items in one list and 1,000,000 values in all. A file in several calls: call it with checkOnly=true and firstRowNumber for every part first (nothing is written), then import the parts, so a wrong row anywhere imports nothing, except values that clash between parts or a limit reached by the parts together.

Parameters

tableIdstringrequired

Table ID from listTables

rowsarrayrequired

Array of row data. When matchFieldsByName=true, use field NAMES as keys. When false, use field IDs. LINKED-RECORD columns resolve per value: sibling "<Field> (id)" column → row IDs → JSON-array string (comma-safe) → exact label → unique case-insensitive label; unresolvable values are returned in unresolvedLinks (row still imports, link skipped — never guessed, never auto-created). Relations are written both directions.

matchFieldsByNameboolean

If true, match columns by field name. If false, use field IDs as keys (default: true)

fieldDefinitionsarray

Optional field definitions to create new fields during import

checkOnlyboolean

Check these rows exactly as an import would, writing nothing (no rows, no columns). To import a file in several calls, check every part first, then import them: a wrong row anywhere then imports nothing, except values that clash between parts or a limit reached by the parts together.

firstRowNumberinteger

The file's row number of rows[0] when a file goes in several calls (default 1), so an error names the row in the file.

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/importRows \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "rows": {},
  "matchFieldsByName": true
}'
POST
/api/v1/tables/exportBase

Export one whole base (all its tables, fields, rows and views) as one file in the format tables_importBase takes. Param "databaseId" (from listDatabases). Returns { formatVersion, exportedAt, base, tables: [{ name, fields, rows, views }] }, the same file the Export button saves. Each row carries its id (__rowId) so an import can put linked records back; a secret column comes back blank. The file is at most 256 KB: a bigger base is refused with its size, so read it one table at a time with tables_getRows instead. For one table only use tables_exportTable.

Parameters

databaseIdstringrequired

The base to export (an id from listDatabases)

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/exportBase \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "databaseId": "example"
}'
POST
/api/v1/tables/importBase

Make a new base from a file tables_exportBase gave. Params: data (required: the whole file, exactly as exported), name (optional: the new base's name; default the file's own name). It always makes a new base with all-new ids in this workspace and never changes, overwrites or deletes an existing base, table or row; a base of the same name becomes a second base. It counts against the plan: the number of bases, the rows a table may hold on plans with a row limit, and the database storage; when a limit is reached nothing is made and the answer says which. Returns { databaseId, tablesCreated, linkedRecordsRestored, unresolvedLinks, message }; unresolvedLinks lists link cells that named a row the file does not hold (nothing is linked for them).

Parameters

namestring

Name for the new base (default: the file's own name)

dataobjectrequired

The whole file tables_exportBase gave, exactly as exported

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/importBase \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "example",
  "data": {}
}'
POST
/api/v1/tables/filterRows

Filter rows by field values using postgres-side WHERE clauses (uses GIN index on data, scales to large tables). Returns { rows, total, tableId, tableName, limit, offset }. Same operator dict as the published-app runtime SDK's entities.<Table>.filter(). Unknown field keys and unknown operators throw 400 with the valid options. Scalar lookup/rollup fields ARE filterable (computed in SQL — direct sources only; chained/list aggregations throw 400 explaining why). Formula fields ARE filterable too (values are materialized into stored data on every write) — EXCEPT formulas using NOW()/TODAY(), which have no stored value and throw 400 with guidance.

Parameters

tableIdstringrequired

Table ID to filter

filterobject

Filter object. Keys are field IDs OR field names (case-insensitive). Multiple keys are AND-ed; { "$or": [ {...}, {...} ] } and { "$and": [...] } group full filter objects and nest arbitrarily. Each value is either a plain primitive (equality), or an operator dict. Operators: $eq, $ne, $gt, $gte, $lt, $lte, $between ([min,max] inclusive), $contains, $startsWith, $endsWith, $regex (Postgres syntax, case-sensitive — prefix (?i) for insensitive), $in, $nin (blanks count as not-in-list), $not (complement of an inner operator dict), $isEmpty, $isNotEmpty. Field-to-field: $eqField/$neField/$gtField/$gteField/$ltField/$lteField compare against ANOTHER field of the same row by name/id — { "Spent": { "$gtField": "Budget" } } finds over-budget rows. Example: { "Status": "todo", "Priority": { "$between": [5, 9] }, "$or": [{ "Tags": { "$contains": "urgent" } }, { "Due": { "$isEmpty": true } }] } Validation: unknown field keys, unknown operators, and operator/value type mismatches throw 400 with the valid options — typos surface immediately instead of returning all (or wrong) rows. Semantics: $contains is case-insensitive and matches LITERALLY (%, _ and \ are escaped); $eq is exact and case-sensitive with NO type coercion ({Score: "50"} does not match the number 50); { field: null } means "is empty"; $in: [] matches NOTHING. Field types: multiselect filters by MEMBERSHIP ($contains value, $in = any-of, plain scalar = has that tag). created_time/updated_time compare as dates ($gte/$lt ranges; ISO strings). Link fields filter by linked ROW ID via the relation table ($contains id, $in [ids], $isEmpty/$isNotEmpty). Caveat: $gt/$gte/$lt/$lte on text fields that store numeric-looking strings ("16", "8") use LEXICOGRAPHIC comparison, so "8" > "10" is true. Use these operators only on fields whose values are stored as proper numbers, or filter then sort/compare client-side for text-stored numerics.

sortstring

Sort spec — rowOrder, createdAt, updatedAt, or ANY FIELD NAME/ID, optionally prefixed with "-" for descending (e.g. "-Total"). Defaults to rowOrder asc. Numbers sort numerically, text case-insensitively, blanks always last; scalar lookup/rollup and self-contained formulas sort server-side too. Link fields, volatile formulas and list aggregations are not sortable (clear 400). Unknown keys throw 400 — never silently ignored.

limitnumber

Max rows per page (default: 100, max: 1000)

offsetnumber

Skip results for pagination

includeReadableboolean

Include human-readable field-name keys in output (extra cost — set true only when you need it; default false)

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/filterRows \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "filter": {},
  "sort": "example"
}'
POST
/api/v1/tables/searchRows

Substring search across all field values in a table. Postgres-side via data::text. No 500-row cap.

Parameters

tableIdstringrequired

Table ID to search in

querystringrequired

Search query string. Matches anywhere in the row's serialized data (field IDs and values).

limitnumber

Max results per page (default: 50, max: 500)

offsetnumber

Skip results for pagination

includeReadableboolean

Include human-readable field names in output

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/searchRows \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "query": "example",
  "limit": 0
}'
POST
/api/v1/tables/upsertRow

Create a row if no match found, or update existing row if match exists. Useful for sync operations.

Parameters

tableIdstringrequired

Table ID

matchFieldIdstringrequired

Field ID to match on (must be unique or will update first match)

matchValueany

Value to match against

dataobjectrequired

Row data with field IDs as keys

includeReadableboolean

Include human-readable output

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/upsertRow \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "matchFieldId": "example",
  "matchValue": {}
}'
POST
/api/v1/tables/getTableSchema

Get table structure/schema. Useful for understanding table layout before creating/updating rows.

Parameters

tableIdstringrequired

Table ID

formatstring

Output format: json (full), array (simple), markdown (documentation)

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/getTableSchema \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "format": "example"
}'
POST
/api/v1/tables/duplicateTable

Clone a table with its structure (fields) and optionally data (rows) and views.

Parameters

tableIdstringrequired

Source table ID to duplicate

newNamestringrequired

Name for the new table

targetDatabaseIdstring

Target database ID (defaults to same database)

includeRowsboolean

Copy all rows from source table

includeViewsboolean

Copy views configuration

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/duplicateTable \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "newName": "example",
  "targetDatabaseId": "example"
}'
POST
/api/v1/tables/getHelp

Get help for Tables API. Call with topic to get focused guidance.

Parameters

topicstring

Topic: "overview", "fields", "rows", "views", "linked", "buttons"

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/getHelp \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "topic": "example"
}'
POST
/api/v1/tables/setAccessRules

Set access rules for a table. Controls who can create/read/update/delete rows in published apps. App owner always has full access.

Parameters

tableIdstringrequired

Table ID from listTables

accessRulesobjectrequired

Access rules per operation (create/read/update/delete). Each is a Condition: a single rule, a legacy flat array (OR), or an { all | any | not } group. Rule types: public, authenticated, creator, field_match, user_property (with op: eq/ne/gt/gte/lt/lte/in/nin/contains/isEmpty/isNotEmpty), has_role, email, function. AND/OR/NOT groups + operators enable any combination.

trackCreatorboolean

Whether to track who creates each row. OMIT to keep the table's current setting — it used to default to true, so a call that only changed a read rule silently re-enabled creator tracking.

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/setAccessRules \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example",
  "accessRules": {},
  "trackCreator": true
}'
POST
/api/v1/tables/getAccessRules

Get access rules for a table

Parameters

tableIdstringrequired

Table ID from listTables

Example Request

curl -X POST https://app.serenitiesai.com/api/v1/tables/getAccessRules \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "tableId": "example"
}'