Creating a REST API
A complete resource API with list, read, create, update, and delete: proper methods, statuses, validation, and scopes.
This tutorial builds a full REST resource: GET/POST /api/v1/tasks and GET/PUT/DELETE /api/v1/tasks/{guid}. It assumes the quickstart. If you haven't registered an endpoint before, do Build Your First API first.
The Shape of a Resource
| Operation | Method + URI | Success status |
|---|---|---|
| List | GET /api/v1/tasks | 200 + array |
| Create | POST /api/v1/tasks | 201 + created document |
| Read one | GET /api/v1/tasks/{guid} | 200 + document, 404 if unknown |
| Update | PUT /api/v1/tasks/{guid} | 200 + updated document, 404 if unknown |
| Delete | DELETE /api/v1/tasks/{guid} | 200 or 204, 404 if unknown |
Each row is one API block (on_startup_register_uri_get, _post, _put, _delete) feeding one handler function. The same trigger → work → reply shape from Block Templates.
GET /tasks, List with Filters
- Trigger
on_startup_register_uri_getwith URItasks→ handler function. - Build the query: optional
statusparam fromhttpconnection_get_params→query_bool_term_fields→query_bool_filter→query_and, withquery_sort_fieldon_meta.createddescending. function_searchon thetasksstorage; respectlimit/offsetparams for pagination.- Reply with
httpconnection_set_json: code 200, data = the results array.
POST /tasks, Create with Validation
- Trigger
on_startup_register_uri_postwith URItasks. - Validate required fields from the request body with
condition_not_empty_valueper field →branch; on the false path reply 400 with{"error": "title is required"}(see validation template). - Map the body to document fields with
mutations_set_bp_field_multiple, thenfunction_create_document_from_mutations. - Reply 201 with the created document (it now has its
_meta.guid).
GET /tasks/{guid}, Read One
- The URI block exposes the guid as a param; fetch with
function_get_documenton the tasks storage. - On its
foundcondition: reply 200 with the document. Otherwise: reply 404 with{"error": "not found"}. Wire both paths from the success/error pins (see error handling).
PUT and DELETE
- PUT: same fetch-first guard, then
function_update_document_mutationswith the changed fields. Reply 200 with the updated document; 404 when missing. - DELETE: soft-delete with
function_remove_document(recoverable), or hard-delete withfunction_delete_documentwhen you mean it. See document lifecycle. Reply 200 with a small confirmation object.
Scopes and Testing
- Scope the collection endpoints with the lock icon:
*publicfor open reads,*loggedinor a custom scope for writes. See Remote Access Control. - Activate the blueprint, then test every row of the table with curl: commands in API workflows.
- When the endpoint 404s right after activation, it's almost always a scope or an inactive blueprint. See Common Issues.
Next Steps
API Guide Conventions, error codes, and rate limits for your API. Storages The queries and mutations behind every row of the table. Block Templates The endpoint and validation shapes in one view.Frequently asked
How do I build a CRUD REST API in RUAL?
One API block per operation: GET and POST /api/v1/tasks for list and create, and GET, PUT and DELETE /api/v1/tasks/{guid} for read, update and delete. Each on_startup_register_uri block feeds one handler function that does the work and replies with the right status: 200 for reads, 201 for creates, 404 for unknown guids.
How do I validate the request body in a RUAL API?
Check each required field with its own condition_not_empty_value block into a branch, and reply 400 on the false path before anything is stored. On the success path, map the body to document fields with mutations_set_bp_field_multiple and create the document from those mutations.
Should a RUAL DELETE endpoint remove or delete the document?
Your choice: function_remove_document soft-deletes and stays recoverable, while function_delete_document hard-deletes when you mean it. Reply 200 with a small confirmation object either way.