REST API Reference
Every Xcrud widget talks to one endpoint, core/ajax_crud.php - here's its request/response shape.
The route parameter
Every request carries a route query parameter identifying which page's configuration to use - it matches whatever value that page's own ->route() call set. The API re-resolves the page's hooks, columns, and validation rules server-side from that route on every single request; it never trusts a client-provided copy of any of it.
Operations
| Operation | HTTP method | Notes |
|---|---|---|
| List | GET | Returns {success, data, meta} - paginated rows plus meta.page/meta.limit/meta.total/meta.sums. |
| Create | POST | JSON body of field values. Runs before_insert()/validation/insert/after_insert() in order. |
| Update | PUT | JSON body of field values, addressed by the row's primary key. Runs before_update()/validation/update/after_update(). |
| Delete | DELETE | Accepts a single id or a bulk ?ids= list. |
| Export | GET | ?export=csv, ?export=xlsx, or ?export=pdf - streams the current filtered/sorted result set as a file download, capped at XcrudConfig::$exportRowLimit rows. |
| Import | POST | ?import=csv with a multipart file upload. Each row runs through the same before_insert()/validation/insert/after_insert() pipeline as a single-row create, capped at XcrudConfig::$importRowLimit rows. |
List response shape
{
"success": true,
"data": [
{ "customerNumber": 103, "customerName": "Atelier graphique", "..." : "..." }
],
"meta": {
"page": 1,
"limit": 10,
"total": 122,
"sums": null
}
}
meta.sums is populated instead of null when a page calls ->sum() or uses ->group_sum_columns() - see Grouped Rows, Sums & Reports.
Every write is validated server-side
A client calling ajax_crud.php directly - bypassing the widget's own JS entirely - cannot reach anything a normal page load couldn't. Create/update requests are validated against the exact same rules the PHP config declares for that route: XcrudConfig::$blacklistedTables/$blacklistedColumns gate which tables/columns exist at all, and each field's own ->validation_required()/->validation_pattern() rules are re-checked on the server, never trusted from the browser. A blacklisted column is never accepted on insert/update regardless of what's in the request body, and an unrecognized column name is silently ignored rather than written. See Security: Blacklisting Tables & Columns for the full model.