API Reference · Endpoints
Endpoints
Jump to: Hosted · Self-Hosted (Core)
Hosted
Base path:
/api-public/v1/PROJECT_ID/builder/MODEL_NAME
Every request requires authentication — see Authentication. Records are scoped to your tenant and project.
List records
GET /api-public/v1/PROJECT_ID/builder/MODEL_NAME
Any query parameter is passed through as a filter.
Response 200:
{ "data": [ { "field": "value" } ] }
Get a single record
GET /api-public/v1/PROJECT_ID/builder/MODEL_NAME/RECORD_ID
Response 200:
{ "data": { "field": "value" } }
If no record matches, the response is still 200 with a null data value, rather than a 404.
Create a record
POST /api-public/v1/PROJECT_ID/builder/MODEL_NAME Content-Type: application/json
{ "title": "New Product", "price": 29.99 }
Payloads are capped at 1MB (413 if exceeded).
Response 201:
{ "data": { "field": "value" } }
Update a record
PUT /api-public/v1/PROJECT_ID/builder/MODEL_NAME/RECORD_ID Content-Type: application/json
{ "price": 24.99 }
Payloads are capped at 1MB (413 if exceeded).
Response 200:
{ "success": true }
Delete a record
DELETE /api-public/v1/PROJECT_ID/builder/MODEL_NAME/RECORD_ID
Response 200:
{ "success": true }
Rate limits
Limits scale with your plan. Exceeding it returns an error response with your current plan name, limit, and an upgrade link.
Self-Hosted (Core)
Base path:
/api-public/v1/PROJECT_ID/TABLE_NAME
Every request requires the X-API-Key header — see Authentication. Records are automatically scoped to your project.
List records
GET /api-public/v1/PROJECT_ID/TABLE_NAME
Query parameters:
| Parameter | Type | Description |
|---|---|---|
page | number | Page number. Default 1. |
limit | number | Results per page. Default 20, capped at 100. |
search | string | Case-insensitive substring match across all string fields. |
sort_field | string | Column to sort by. |
sort_dir | string | asc or desc. Default asc. |
| any other key | string | Exact-match filter on that column, e.g. ?status=active. |
Response 200:
{
"records": [ { "prod_id": "value", "title": "value", "price": 24.99 } ],
"total": 42,
"page": 1,
"limit": 20,
"pages": 3
}
Columns marked hidden: true on the model are stripped from every record — see Field Types.
Get a single record
GET /api-public/v1/PROJECT_ID/TABLE_NAME?id=RECORD_ID
Response 200:
{ "record": { "prod_id": "value", "title": "value" } }
Returns 404 if no record matches id.
Create a record
POST /api-public/v1/PROJECT_ID/TABLE_NAME Content-Type: application/json
{ "title": "New Product", "price": 29.99 }
project_id, created_at, and updated_at are set by the server on every insert.
Response 201:
{ "success": true, "record": { "title": "New Product", "price": 29.99 } }
Update a record
PATCH /api-public/v1/PROJECT_ID/TABLE_NAME Content-Type: application/json
{ "id": "the-record-id", "id_column": "prod_id", "price": 24.99 }
| Field | Required | Description |
|---|---|---|
id | Yes | The value to match. 400 if missing. |
id_column | No | The column id is matched against. Defaults to id — set this explicitly if the model's primary key isn't literally named id. |
Response 200:
{ "success": true, "record": { "field": "value" } }
Delete a record
DELETE /api-public/v1/PROJECT_ID/TABLE_NAME Content-Type: application/json
{ "id": "the-record-id" }
id is required, returns 400 if missing.
Known limitation: unlike Update, Delete does not currently accept
id_column— it always matches against theidcolumn. If your model's primary key isn't literally namedid(e.g.prod_id), deleting through this endpoint won't work yet. Delete records with a non-idprimary key directly through the console instead.
Response 200:
{ "success": true }
Errors
{ "error": "message" }
| Status | Meaning |
|---|---|
401 | Missing or invalid API key. |
404 | Table or record not found. |
429 | Rate limit exceeded. |
500 | Unexpected server error. |
Rate limits
Each API key is limited to 100 requests per minute, flat.
Exceeding it returns a 429 with an error message describing the limit.