Appearance
grid
32 endpoints.
GET /api/v1/grid
List Grids
Grids the current user may reach — drives the nav (menu-as-permission).
Read straight from erp_modules (no per-grid hydration needed for the menu). account_scoped lets the sidebar group account-filtered grids under the ad-account selector and keep the rest above it.
200 — Successful Response
json
{}GET /api/v1/grid/{slug}/options
Grid Options
Column definitions + metadata. The frontend builds AG Grid colDefs from this.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string | |
include_inactive | query | no | boolean |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/grid/{slug}/data
Grid Data
Tenant-scoped, soft-delete-filtered, paginated/sorted/searched rows.
parent_field/parent_value scope the grid to a master row (drill-down), e.g. ad-sets filtered to a campaign via parent_field=campaign_id.
date_from/date_to (YYYY-MM-DD) bound the grid to a period on models that carry a date column (e.g. Insights) — used so a dashboard card's deep-link opens exactly the rows that card aggregates over.
By default only active rows are returned (paused campaigns, suspended tenants, deactivated users, …). Pass include_inactive=true to show all.
include_deleted=true additionally surfaces soft-deleted rows (those with deleted_at set) — an admin-only recovery view, gated here the same way delete is, so a crafted request from a non-admin can never reveal removed records.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string | |
page | query | no | integer | |
per_page | query | no | integer | |
sort | query | no | ||
order | query | no | ||
search | query | no | ||
key | query | no | ||
parent_field | query | no | ||
parent_value | query | no | ||
include_inactive | query | no | boolean | |
include_deleted | query | no | boolean | |
date_from | query | no | ||
date_to | query | no | ||
filters | query | no | ||
scope | query | no | ||
instance | query | no | Platform-admin only. Read a specific site's DB instead of the one resolved from this request's Host — for drilling into a foreign_lookup link whose row actually lives on a different site (see <field>__link_site, stamped by _apply_lookups when a provider crossed sites, e.g. acc-sales-invoices on the Customer Portal resolving its Reseller User against 'tc'). |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/grid/{slug}/refresh
Grid Refresh
Pull the grid's data fresh from its live source, then report what was synced — backs the live_sync grids (e.g. Meta Ads campaigns/ads): the frontend calls this when the module is opened so the page mirrors the provider's current state. A no-op for non-live grids or ones with no refresh_fn (see GridConfig.refresh_fn).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/grid/{slug}/action/{key}
Grid Action
Run a registered grid action over the selected rows (cf. GridAction::handle).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string | |
key | path | yes | string |
Request body
json
{
"type": "object",
"additionalProperties": true,
"default": {},
"title": "Body"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/grid/{slug}/stats
Grid Stats
Stat cards — each an aggregate over the grid's tenant + soft-delete scope.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string | |
filters | query | no | ||
parent_field | query | no | ||
parent_value | query | no | ||
scope | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/grid/{slug}/board
Grid Board
Rows grouped by board.group_field (e.g. Deals by pipeline stage) — the SAME tenant/soft-delete/search/filter scope as GET /data, just shaped as groups instead of a flat page. Every matching row is returned ungrouped by page (a board shows the whole working set, not one page at a time).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string | |
search | query | no | ||
filters | query | no | ||
scope | query | no | ||
include_inactive | query | no | boolean |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/grid/{slug}/board/move
Grid Board Move
Move one row to a different board group (a Kanban card drag). Uses the board's move_handler when set (e.g. Deals recomputes status and logs a stage-change activity); otherwise a generic group_field = group_id update.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Body"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/grid/{slug}/settings
Get Settings
Current editable module settings + whether the caller may change them.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PUT /api/v1/grid/{slug}/settings
Update Settings
Persist a super-admin's module-setting changes (cf. updateSettings).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Body"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PUT /api/v1/grid/{slug}/fields/reorder
Reorder Fields
Persist field order (and optionally tab) for a grid (cf. reorderFields).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Body"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PUT /api/v1/grid/{slug}/rows/reorder
Reorder Rows
Persist a drag-to-reorder: ids are rows in the order they now sit.
Cannot collide with PUT /{slug}/{row_id} — that route only ever matches two path segments, this one has three.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Body"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/grid/{slug}/fields/tabs
Field Tabs
Distinct tab names already in use across this grid's fields — backs the Field Config editor's Tab dropdown, so admins pick an existing form grouping instead of typo-ing a near-duplicate one.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/grid/{slug}/fields/{field}/config
Get Field Config
One field's display/form config + whether the caller may change it. Backs the column-menu "Edit Field Config" editor.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string | |
field | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PUT /api/v1/grid/{slug}/fields/{field}/config
Update Field Config
Persist a super-admin's per-field config change. Flags the field is_customized so the every-boot reseed preserves it (see seed_grid).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string | |
field | path | yes | string |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Body"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/grid/{slug}/fields/{field}/lookup-targets
Field Lookup Targets
Registered modules a foreign_lookup field may point at — backs the Field Config editor's Foreign Lookup tab "Foreign DB Table" dropdown. Deliberately scoped to the registered grids' tables, not raw DB schema introspection: a lookup must link to a module, never an arbitrary/unregistered table (see the standing "lookup fields must link to module" rule and _hydrate's admin-configured-lookup resolution).
Both kinds of module count. TABLE_TO_GRID covers the ones with a model in this app; REMOTE_TABLE_TO_GRID covers the ones with no model, read through a provider — the pbx box's v_gateways and friends.
remote used to be a property of that second list: its rows lived in another system and no local SELECT could reach them. Since the portal moved into the box's fusionpbx database that is no longer true of most of it — 42 of the 45 are in public, one join away — so remote is now decided per target by asking where the table actually is, rather than by which registry it came from. Only call_history (the call_records database), p_numbering_plan and registrations (FreeSWITCH's own) are still genuinely elsewhere.
The distinction still matters to the editor: a co-located target can offer its real columns, a remote one can only offer what its grid declares.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string | |
field | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/grid/{slug}/fields/{field}/lookup-columns
Field Lookup Columns
Columns of a lookup-target module's table — backs the Field Config editor's Key/Display/Sort Column dropdowns, populated once a target module is chosen (see field_lookup_targets).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string | |
field | path | yes | string | |
table | query | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/grid/{slug}/fields/available
List Available Fields
Keys this grid's rows carry that are NOT yet columns on it.
Backs the right-click "Add Field" picker. Deliberately derived from the grid's own DATA rather than from the model's columns: a provider grid (Lubb Sites, the pricelists, Group Reporting) builds rows that are nothing like its declared model, and offering model columns there would list fields that can never be populated. One page of rows is enough to see the shape.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/grid/{slug}/fields
Create Field
Add a column to this grid from the right-click menu.
Surfaces a key the rows ALREADY carry; it does not alter any table. That is the whole scope on purpose — creating a database column from a context menu is a migration wearing a menu item's clothes, and this estate has no Alembic to undo one.
Flagged is_customized so the every-boot reseed keeps it, exactly as update_field_config does for an edited field.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Body"
}201 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/grid/{slug}/stats/config
Stat Cards Config
ALL the grid's stat cards, deleted ones included — backs the Module Settings modal's Stat Cards tab (the /stats endpoint only returns live cards, with computed values).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/grid/{slug}/stats/{key}
Delete Stat Card
Delete one stat card from the grid, site-wide (super-admin only).
DB-stored cards (erp_module_stats) are soft-deleted. Provider-generated cards (stats_provider) have no DB row — their removed keys are persisted on erp_modules.removed_cards instead, so the grid_stats endpoint filters them out on every load.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string | |
key | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/grid/{slug}/stats/restore
Restore Stat Cards
Reactivate deleted stat cards (super-admin only) — one card when the body names a key (Module Settings' per-card Restore), else all of them (the context menu / all-deleted inline link).
Provider-generated cards (stats_provider) read from erp_modules.removed_cards; DB-stored cards read from erp_module_stats.active=False.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"title": "Body"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/grid/{slug}/layout
Get Layout
Return the saved AG Grid layout for a grid, or a null layout when none is saved yet. Answered 200-with-nulls (not 404) on purpose: this fetch fires on every grid load and "no saved layout" is the normal case, not an error — a 404 here just spams the browser console with a stack trace even though the frontend already falls back to autosized default columns.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PUT /api/v1/grid/{slug}/layout
Save Layout
Save (upsert) the shared DEFAULT layout for a grid. Platform super-users only — see :func:_can_save_layout.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Body"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/grid/{slug}/layout
Reset Layout
Delete the saved DEFAULT layout for a grid (reset to defaults). Platform super-users only, same gate as save_layout — resetting the shared layout is as destructive as overwriting it. Scoped to name IS NULL so saved NAMED VIEWS are left intact.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/grid/{slug}/views
List Views
Every named view for a grid: [{id, name}] ordered by name. Fires on grid load (like /layout) so 200-with-empty is the normal empty case.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PUT /api/v1/grid/{slug}/views
Save View
Create or update a named view (upsert by grid_key + name). Super-admin only.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Body"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/grid/{slug}/views/{view_id}
Get View
One named view's column/filter state.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string | |
view_id | path | yes | integer |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/grid/{slug}/views/{view_id}
Delete View
Delete a named view. Super-admin only.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string | |
view_id | path | yes | integer |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/grid/{slug}
Grid Create
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Body"
}201 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PUT /api/v1/grid/{slug}/{row_id}
Grid Update
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string | |
row_id | path | yes | string |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Body"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/grid/{slug}/{row_id}
Grid Delete
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string | |
row_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}