Repository navigation
EN CRUD and Queries
English · Türkçe · Languages / Diller
Scope: JSON API Forge 0.5.1 · Source review: 17 September 2026 · Language: English
A SQL resource maps a table to its permitted HTTP operations. A useful small resource looks like this:
{
"resources": [
{
"database": "primary",
"table": "notes",
"path": "notes",
"auto_create": true,
"columns": {
"id": {"type": "integer", "primary_key": true, "nullable": false},
"title": {"type": "string", "nullable": false, "max_length": 160},
"status": {"type": "string", "default": "draft", "index": true}
},
"writable_fields": ["title", "status"],
"allowed_filters": ["status"],
"filter_operators": ["eq", "ne", "in"],
"search_fields": ["title"],
"allowed_sort": ["id", "title"],
"permissions": {
"list": "notes.list", "read": "notes.read", "create": "notes.create",
"update": "notes.update", "delete": "notes.delete"
}
}
]
}Let P be the project API prefix. Route availability depends on enabled, allowed_actions and batch/count settings.
| Method/path | Behavior |
|---|---|
GET P/notes |
Bounded list |
POST P/notes |
Create a row |
GET P/notes/{item_id} |
Read one row |
PATCH P/notes/{item_id} |
Update supplied fields |
PUT P/notes/{item_id} |
Replace the writable representation while preserving identity/policy fields |
DELETE P/notes/{item_id} |
Delete or configured soft-delete |
GET P/notes/_count |
Count under the same visibility/filter policy |
Get the actual route set from forge routes and the project's /_openapi.json. A static Wiki table is not a universal contract for every application.
readable_fields is the read allowlist; hidden_fields excludes fields; writable_fields controls client writes. Prefer explicit allowlists. create_schema and update_schema add JSON Schema validation. A database column's existence does not grant client write access.
Primary-key, tenant, owner and soft-delete fields are server-controlled. Keep them out of client write lists. See row authorization for owner_actions and tenant_field.
GET P/notes?status=draft&limit=20&offset=0&sort=-id
GET P/notes?status__in=draft,published&q=api
SQL operators are eq, ne, gt, gte, lt, lte, in, like, ilike and isnull. Both the field and operator must be allowed. q searches only search_fields. sort=-field requests descending order.
v0.5.1 behavior: the SQL filter builder silently skips unknown or disallowed filters. Check that a typo has not broadened your results. Filters are not authorization; tenant/owner constraints are applied separately.
Offset responses contain items, limit and offset; no automatic total is promised. Use _count when a total is needed, accounting for its cost on large tables.
pagination_mode: "cursor" uses cursor_field and a primary-key tie-breaker for stable keyset pagination. Responses contain next_cursor and has_more. Treat cursors as opaque and return them unchanged. Cursor mode rejects offset and sort; offset mode rejects cursor. Index the chosen cursor field and primary key appropriately.
The Python SDK's synchronous iter_items helper uses offsets. For cursor resources, follow next_cursor in your own bounded loop.
batch_enabled defaults to false; max_batch_size defaults to 100. Follow each batch endpoint's actual OpenAPI body contract. Do not assume every API called a batch has identical all-or-nothing behavior. Soft-delete visibility applies to list/read/count; retaining physical rows also requires an explicit retention and cleanup policy.
This page describes the behavior at the pinned commits below. Recheck these contracts when upgrading.