Foleon's API gives you the ability to create and edit Foleon content completely programatically. Unlike traditional CMS APIs that might require you to send an entire page back and forth, Foleon uses a normalized data structure and patch-based mutations to make precise updates to your content.
Foleon Content objects (Pages, Templates, Modules, Themes, Overlays, etc.) are JSON representations of the content.
While Foleon content appears as a nested visual hierarchy (e.g. Page → Block → Row → Column → Text), the underlying JSON is normalized (flat). This means entities are stored in collections based on their idenity, rather than being nested deep inside one another.
To gain a better understanding of the structure of your content you can use the GET operation on the /content/ endpoint for your content type. GET operation on the /content/ endpoint for your content type.
When you perform a GET operation on a content type (like a PAGE), the endpoint returns a JSON object containing the content object, which acts as a library of every entity present.
Under
content, you will find keys like "block", "row", or "text-item". Each of these is a collection of entities of that specific type.Each specific entity is a key-value pair within those collections, where the key is the element's UUID and the value an object containing all the entity's properties.
Every entity has an identity string (e.g., "block" or "text-item") to help you identify its type.
Since the JSON isn't nested, entities use the
refsarray andparentobject to point to their logical children and parent respectively.
Why this matters: Because the structure is flat, your "path" to an object is almost always relatively short. You don't need to traverse the whole tree; you just need the entity's identity and the entity's UUID.
"block": {
"19c2c02e-b968-45b6-9a56-3e0a089393ac": {
"id": "19c2c02e-b968-45b6-9a56-3e0a089393ac",
"refs": [
{
"id": "c5e12c80-da0f-4899-b4aa-ad3173f57f0c",
"identity": "row"
}
],
"parent": {
"id": "d8625a73-2784-4036-8d3c-b35f366876bd",
"identity": "page"
},
"styles": {
"20": {},
"30": {},
"40": {},
"50": {
"box": {
"height": "740"
}
}
},
"options": {},
"identity": "block",
"customIdentifier": null,
"triggerContentAnimationOnce": false
}
},To change content, you use the Mutation Endpoint which allows you to add, remove and replace all elements in the content. Instead of overwriting the whole page, you send Immer-style patches" that describe specific changes. Immer-style patches describe state changes as a list of operations, similar to JSON Patch.
A patch is an object with three fields:
| Field | Type | Description |
|---|---|---|
| op | string | The operation: "add", "replace", or "remove". |
| path | array | The breadcrumb path to the property you are changing. |
| value | any | The new data (required for add and replace). |
{
"op": "replace",
"path": ["text-item", "60b9663d-fab5-44f7-942c-3721063fde2e", "text"],
"value": "My text"
}This patch means: replace the value of text-item.60b9663d-fab5-44f7-942c-3721063fde2e.text to "My text"
Design properties are stored in the styles object of an entity. Foleon uses numeric keys to represent different screen widths (breakpoints):
- 50: Desktop (Base styles)
- 40: Tablet Landscape
- 30: Tablet Portrait
- 20: Mobile
If you want to change the height of a block on Mobile, your path would target the "20" key: ["block", "<SOME UUID>", "styles", "20", "box", "height"]
The most efficient way to learn how to format a patch is to let the Foleon Editor do the work for you.
Manually Edit: Open your Doc in the Foleon Editor and make the change you want to automate (e.g., change a button color or swap an image).
Inspect Mutations: Call the GET operation on the mutations endpoint for that page.
Replicate: Look at the most recent entries in the response. The API will show you the exact path and value used by the Editor. You can now copy this logic into your own script.
Atomic Batches: You can send an array of multiple patches in a single request. This ensures all changes are applied at once.
Safety First: Perform a
GETon the content first to verify the UUIDs exist before sending a replace or remove mutation.Development Sandbox: Use a duplicate of your content when testing scripts to avoid breaking important content.