Create, Read & Update
Single-record lifecycle over the Records API. For removing and merging rows see Upsert & Delete; for listing many rows, Filtering, Sorting & Pagination; for bulk writes, Batch Operations.
All write bodies use the canonical { "fields": { ... } } envelope described in the Records Overview.
Create a record
POST /api/tables/contacts/records
{
"fields": {
"email": "john@example.com",
"first_name": "John",
"last_name": "Doe"
}
}| Status | Meaning |
|---|---|
201 Created |
Record created; body is the stored record with id and authorship |
400 Bad Request |
Missing required field or invalid field-type value |
401 Unauthorized |
No active session |
404 Not Found |
Table does not exist, or the caller may not access it |
409 Conflict |
Unique-constraint violation — "Resource already exists" |
The response carries the generated id, the fields echo, and the authorship metadata (createdBy, createdAt, updatedAt).
Read a record
GET /api/tables/contacts/records/42| Status | Meaning |
|---|---|
200 OK |
Record returned |
401 Unauthorized |
No active session |
404 Not Found |
Record absent or not visible to the caller (anti-enumeration) |
Fields the caller lacks read permission for are omitted from the response, so the same record can return a different field set depending on the caller's role and field-level permissions.
Pass ?includeDeleted=true to read a soft-deleted row. Note that on this endpoint format accepts only display — ?format=raw returns 400 VALIDATION_ERROR, and omitting the parameter is how you ask for raw values.
Update a record
PATCH performs a partial update: only the fields present in the body are written, and omitted fields are left untouched.
PATCH /api/tables/contacts/records/42
{
"fields": {
"status": "active"
}
}| Status | Meaning |
|---|---|
200 OK |
Record updated; updatedBy/updatedAt re-stamped |
400 Bad Request |
Invalid field-type value or constraint violation |
401 Unauthorized |
No active session |
404 Not Found |
Record absent, not visible, or not writable |
409 Conflict |
Optimistic-lock failure (stale write) |
A write-permission denial returns 404, not 403. If the caller can read a record but may not modify it, the update answers 404 so the write boundary is not discoverable by probing. Do not treat a 404 on PATCH as proof the record is gone.
Optimistic locking
Include a top-level updatedAt token alongside fields to guard against lost updates. The server compares it against the record's stored updated_at column and rejects a divergent write.
PATCH /api/tables/contacts/records/42
{
"fields": { "status": "active" },
"updatedAt": "2025-01-15T10:30:00Z"
}A stale token returns 409 Conflict: "The record was modified after you last read it. Reload the latest version and retry."
The check is skipped entirely — the write simply proceeds — in three cases: the token is absent, the stored record has no updated_at, or either value cannot be parsed as a timestamp. Optimistic locking is therefore opt-in per request, and a client that forgets the token silently gets last-write-wins.
Delete a record
Moved to Upsert & Delete.
Upsert a record
Moved to Upsert & Delete.
Display vs raw formatting
Moved to Upsert & Delete.
Related pages
- Upsert & Delete — merging rows, removing them, and display formatting.
- Records Overview — envelope, authorship, cross-cutting rules.
- Filtering, Sorting & Pagination — the list query grammar.
- Batch Operations — bulk create/update/delete/upsert.
- Table Permissions — RBAC and field-level access.
Last updated August 11, 2026
This documentation was written with AI, so errors or outdated content are possible. Sovrium is in beta. Contributions and corrections are welcome.