Once an entity is defined, its records are served by your app's endpoint. All six routes share one generic execution path, so auth, plan limits, encryption, and indexing behave identically for every entity.
POST /app/{orgcode}/create/{entity} insert (auto keys, formula, encryption, indexes)
GET /app/{orgcode}/item/{entity}/{id} read one (projected); unknown id -> 404
PUT /app/{orgcode}/update/{entity}/{id} update fields; recompute formula; re-validate
DELETE /app/{orgcode}/delete/{entity}/{id} delete record (+ unique sentinels)
GET /app/{orgcode}/list/{entity} list (see Listing & querying)
GET /app/{orgcode}/count/{entity} { count } Request lifecycle
Every CRUD request flows through the same steps:
{token} placeholders are resolved against path, body, query, and JWT claims.What create does
On create, the runtime checks plan limits (a 429 with an upgrade URL if exceeded), generates auto keys (guid, autoincrement), resolves the record keys, stamps index attributes, writes audit fields, encrypts encrypted fields, runs any before-events, writes the record, and best-effort indexes it for search.
Before-events can block a write
If a synchronous before-event hook fails, the create returns 424 and the record is not written. See Events & automations.
Views & projections
A Views map on each read/create config decides what crosses the wire. ?view=<name> overrides the default per request.
- Read projection (get/list) — choose fields, rename with
as, cast types, hide withvisible:false, fetchs3fields, or enrichlookup(foreign-key) fields. - Create/update response — returns only the fields named in the response view; if none is configured it returns just
id. The raw item is never echoed. - Encrypted fields are stripped from every response regardless of the view.
Only listed fields are returned
Once a view has a projection, only the fields it lists appear in the response — a field you don't list never shows up, whatever its type. A listed field comes back under its as name (product_ref with as: product_id is returned as product_id, never product_ref). Get and list follow the same rules.
Showing a name instead of an id (lookup)
A record stores the other record's id (say product_ref). To return the product's name as well, add a separate new field to the get/list projection with type: "lookup". Keep the id as its own plain entry if you also want the id back.
{
"id": { "type": "string", "visible": true },
"product_ref": { "type": "string", "as": "product_id", "visible": true },
"product_name": {
"type": "lookup",
"lookupOn": "product_ref",
"sourceapi": "get-product",
"passLookupAs": "id",
"fieldNameFromLookupApi": "name",
"visible": true
}
} The response then contains product_id (the stored id) and product_name (read from the product's get API). lookupOn is the stored id field, sourceapi is the other entity's get config, passLookupAs is the parameter that get API expects for the id, and fieldNameFromLookupApi is the field to return.
Give the lookup its own name
Don't define the lookup under the id field's own name (a lookup entry called product_ref whose lookupOn is also product_ref). Use a new name such as product_name.
Add a named view later
Generated entities ship with default (all non-encrypted fields) and compact (id + name). Add views like summary afterwards with PUT /api/{api} and a merged Views map — no record changes needed.