Skip to content

Entity endpoints

The endpoints every table gets: list, count, get, create, update, delete, bulk create and update, upsert, update many, delete many and restore, with ETags and idempotency keys.

Last updated September 17, 2026

On this page

Every table (entity) is a collection at /api/entities/<Entity>. The name is the table's name as the Database tab shows it, case-sensitive.

Verb and pathDoes
GET /api/entities/<E>List records, with filtering, search, sorting and paging
GET /api/entities/<E>/countCount records matching a filter
GET /api/entities/<E>/<id>One record
POST /api/entities/<E>Create a record
PUT or PATCH /api/entities/<E>/<id>Update a record (merge: fields you omit keep their value)
DELETE /api/entities/<E>/<id>Delete a record (soft)
PUT /api/entities/<E>/<id>/restoreBring a deleted record back
POST /api/entities/<E>/bulkCreate many records in one call
PUT /api/entities/<E>/bulkUpdate many records by id, all or nothing
POST /api/entities/<E>/upsertCreate or update by a match on one to three fields
PATCH /api/entities/<E>/update-manyApply one change to every record matching a filter
DELETE /api/entities/<E>?q=...Delete every record matching a filter

Records

A record carries the table's own fields plus id, created_date, updated_date and created_by_id (secret keys only). Those four are set by the platform; a write that tries to set one is refused.

JSON
{
  "id": "b7a1...",
  "client_name": "Ana Lewis",
  "date": "2026-06-12",
  "paid": true,
  "created_date": "2026-06-08T16:12:04Z",
  "updated_date": "2026-06-08T16:12:04Z",
  "created_by_id": "u_4f2..."
}

Creating and updating

Shell
curl -X POST https://<your app address>/api/entities/Booking \
  -H "X-Api-Key: pxa_sk_..." -H "Content-Type: application/json" \
  -d '{"client_name": "Ana Lewis", "date": "2026-06-12"}'

curl -X PATCH https://<your app address>/api/entities/Booking/b7a1... \
  -H "X-Api-Key: pxa_sk_..." -H "Content-Type: application/json" \
  -d '{"paid": true}'

A body may only name fields the table declares; an unknown name is refused as unknown_field with the list of real fields in the message. Required fields, types and enum values are checked and an invalid record names the field.

Safe updates with ETags

A single record answers with an ETag. Send it back as If-Match on an update or delete and the write is refused with 412 if someone changed the record in between. Send it as If-None-Match on a read to get a 304 when nothing changed.

Safe retries with idempotency keys

Add an Idempotency-Key header (any unique string, a UUID is ideal) to a write. Repeating the same request with the same key within 24 hours replays the first answer instead of doing the work again, so a retry after a timeout can never create a second record. The reply carries Idempotent-Replayed: true.

Bulk, upsert and many-at-once

  • Bulk create takes an array of records and returns the created records.
  • Bulk update takes an array of objects each carrying an id plus the fields to change. All or nothing.
  • Upsert takes match (one to three field names, such as an external id) and records; a record whose match fields equal an existing one is updated, otherwise created. Each returned record says created: true|false. A match that fits more than one record is refused.
  • Update many and Delete many apply to every record matching a filter. A filter is required; without one the call would mean every record, which is not something you can ask for by omission. Each answers with how many were touched and their ids.

Deleting and restoring

Deletes are soft: the record stops appearing and is not destroyed. A secret key can list deleted records with ?deleted=only or ?deleted=include, and PUT .../restore brings one back. Restoring a live record answers 200 with restored: false.

Was this page helpful?