Skip to content

Powered by Grav + Helios

Flex Objects

Flex Objects

Endpoints for managing Flex Object directories and their records: listing directories and blueprints, full CRUD on objects, YAML export, and per-object media (files stored alongside the object in its own folder).

Endpoints for managing Flex Object directories and their records: listing directories and blueprints, full CRUD on objects, YAML export, and per-object media (files stored alongside the object in its own folder).

Get Flex Config

GET /flex-objects/config
Return UI-relevant Flex Objects plugin configuration (never secrets). Used by the admin to bootstrap the Flex Objects UI.
JSON
{"data": {"enabled": true, "built_in_css": true, "admin_list": {"per_page": 15}}}

Response Codes

200 Success.
401 Unauthorized.
403 Missing `api.access` permission.

Lightweight configuration endpoint. The list of directories is returned separately by GET /flex-objects so callers that only need config stay small.

List Directories

GET /flex-objects
List the enabled custom Flex directories the current user is allowed to view, with their admin list/edit config, search settings, and resolved list-column field types. Built-in directories that already have dedicated admin UI (pages, user-accounts, user-groups) are excluded.
JSON
{"data": [{"type": "contacts", "title": "Contacts", "icon": "fa-address-book", "list": {"fields": {"name": {}, "email": {}}}, "field_types": {"name": "text", "email": "email"}}]}

Response Codes

200 Success.
401 Unauthorized.
403 Missing `api.access` permission.

Each entry's type is the Flex directory key you pass as {type} to the object endpoints below. Directories the user lacks list permission on are omitted from the result.

List Blueprints

GET /flex-objects/blueprints
List every available Flex directory blueprint, including hidden and currently-disabled ones. Powers the directory picker on the plugin settings page.
JSON
{"data": [{"url": "blueprints://flex-objects/contacts.yaml", "legacy_url": null, "type": "contacts", "title": "Contacts", "description": "Address book"}]}

Response Codes

200 Success.
401 Unauthorized.
403 Missing `api.access` permission.

legacy_url carries the pre-existing blueprint alias (when one exists) so saved settings that still reference the old form can be matched.

List Objects

GET /flex-objects/{type}
List the objects in a Flex directory with search, sorting, and pagination. Each item is reduced to the directory's configured list fields (plus `key`).

Parameters

Name Type Description
type required string The Flex directory type (e.g. `contacts`).
page optional integer Page number for pagination (default 1).
per_page optional integer Number of results per page (default 20, max 1000).
search optional string Search term applied across the directory's searchable fields.
sort optional string Field to sort by.
order optional string Sort direction: `asc` (default) or `desc`.
JSON
{"data": [{"key": "ada", "name": "Ada Lovelace", "email": "[email protected]"}], "meta": {"total": 1, "page": 1, "per_page": 20}}

Response Codes

200 Success.
401 Unauthorized.
403 Missing the directory's `list` permission.
404 Directory type not found or not enabled.

The key on each item is the object identifier you pass as {key} to the single-object endpoints.

Get Object

GET /flex-objects/{type}/{key}
Fetch a single object by key, returning its full serialized data. The response carries an `ETag` you can use for optimistic concurrency on update.

Parameters

Name Type Description
type required string The Flex directory type (e.g. `contacts`).
key required string The object key.
JSON
{"data": {"key": "ada", "name": "Ada Lovelace", "email": "[email protected]"}}

Response Codes

200 Success.
401 Unauthorized.
403 Missing the directory's `read` permission.
404 Directory or object not found.

Keep the returned ETag and send it back as an If-Match header when updating, so a concurrent change is detected instead of silently overwritten.

Create Object

POST /flex-objects/{type}
Create a new object in a Flex directory. The request body holds the object's field values. The new key is assigned by the directory's storage and returned in the response and the `Location` header.

Parameters

Name Type Description
type required string The Flex directory type (e.g. `contacts`).
JSON
{"name": "Grace Hopper", "email": "[email protected]"}
JSON
{"data": {"key": "grace-hopper", "name": "Grace Hopper", "email": "[email protected]"}}

Response Codes

201 Object created. The `Location` header points to the new object.
401 Unauthorized.
403 Missing the directory's `create` permission.
422 Validation error (the object could not be created from the supplied data).

Post to the collection address (no key segment). To attach files to the object afterwards, use the Upload Object Media endpoint below with the key returned here.

Update Object

PATCH /flex-objects/{type}/{key}
Update an existing object. The request body contains only the fields to change (a partial merge). Optionally send an `If-Match` header with the ETag from a prior fetch to guard against concurrent edits.

Parameters

Name Type Description
type required string The Flex directory type (e.g. `contacts`).
key required string The object key.
JSON
{"email": "[email protected]"}
JSON
{"data": {"key": "grace-hopper", "name": "Grace Hopper", "email": "[email protected]"}}

Response Codes

200 Object updated. The response carries the new `ETag`.
401 Unauthorized.
403 Missing the directory's `update` permission.
404 Directory or object not found.
409 The supplied `If-Match` ETag is stale; the object changed since you fetched it.
422 Validation error.

This is a partial update: fields you omit are left untouched. Use PATCH, not POST (posting to an object URL is not allowed).

Delete Object

DELETE /flex-objects/{type}/{key}
Delete an object from a Flex directory. For folder-based directories this also removes the object's folder, including any attached media.

Parameters

Name Type Description
type required string The Flex directory type (e.g. `contacts`).
key required string The object key.

Response Codes

204 Object deleted.
401 Unauthorized.
403 Missing the directory's `delete` permission.
404 Directory or object not found.

Returns no content on success.

Export Directory

GET /flex-objects/{type}/export
Export every object in a directory as a single YAML document, returned as a file download (keyed by object key).

Parameters

Name Type Description
type required string The Flex directory type (e.g. `contacts`).

Response Codes

200 YAML file download (`Content-Disposition: attachment`).
401 Unauthorized.
403 Missing the directory's `list` permission.
404 Directory type not found or not enabled.

The response is application/x-yaml with a filename like contacts-YYYY-MM-DD.yaml, not the standard JSON envelope.

List Object Media

GET /flex-objects/{type}/{key}/media
List the media files attached to a single object. For folder-based directories these live in the object's own storage folder, alongside its data file.

Parameters

Name Type Description
type required string The Flex directory type (e.g. `contacts`).
key required string The object key.
JSON
{"data": [{"filename": "avatar.png", "type": "image/png", "size": 20480, "url": "/user/data/flex-objects/contacts/ada/avatar.png"}]}

Response Codes

200 Success.
401 Unauthorized.
403 Missing the directory's `read` permission.
404 Directory or object not found.
422 The directory has no per-object media folder (it uses single-file storage).

Object media requires folder-based storage (one folder per object, e.g. user-data://flex-objects/contacts/{id}). Directories that keep all records in a single shared file have nowhere to store per-object files, and the endpoint returns 422.

Upload Object Media

POST /flex-objects/{type}/{key}/media
Upload one or more files to an object. Files are stored in the object's own folder, next to its data file, for folder-based directories.

Parameters

Name Type Description
type required string The Flex directory type (e.g. `contacts`).
key required string The object key.
file required file File(s) to upload (multipart/form-data). Nested fields like `file[]` are supported.
JSON
{"data": [{"filename": "avatar.png", "type": "image/png", "size": 20480}]}

Response Codes

201 File(s) uploaded; the response lists the object's current media.
401 Unauthorized.
403 Missing the directory's `update` permission.
404 Directory or object not found.
422 No file supplied, a disallowed file type or size, or a directory without per-object media folders (single-file storage).

Send the file as a multipart/form-data request (set Content-Type: multipart/form-data), not JSON. Uploads are validated against Grav''s dangerous-extensions list and a 64 MB size cap. Requires folder-based storage for the directory (one folder per object); directories that use single-file storage return 422.

Delete Object Media

DELETE /flex-objects/{type}/{key}/media/{filename}
Delete a single media file from an object's folder (along with any `.meta.yaml` sidecar).

Parameters

Name Type Description
type required string The Flex directory type (e.g. `contacts`).
key required string The object key.
filename required string The media filename to delete.

Response Codes

204 File deleted.
401 Unauthorized.
403 Missing the directory's `update` permission.
404 Directory, object, or file not found.
422 The directory has no per-object media folder (single-file storage).

Returns no content on success.