Fragments API Basics
Liferay’s headless-admin-fragment module provides REST services for Fragment Sets and Fragments in a site (Liferay’s unit for grouping pages and content). With these services, you can create, retrieve, update, and delete Fragment Sets and the Fragments they contain. Here, you call these services using cURL commands.
This API is available behind the beta feature flag “Fragment Management API” (LPD-39244). Because it’s a beta feature, these endpoints are still evolving and can change. See Beta Feature Flags to enable it.
A Fragment Set groups related Fragments together. A Fragment is a single reusable page element that belongs to a Fragment Set. Because a Fragment always belongs to a Fragment Set, you must create the Fragment Set first.
Add a Fragment Set
Start a new Liferay DXP instance by running
docker run -it -m 8g -p 8080:8080 liferay/dxp:2026.q1.9-lts
Sign in to Liferay at http://localhost:8080 using the email address test@liferay.com and the password test. When prompted, change the password to learn.
Then, follow these steps:
-
Enable the Fragment Management API beta feature flag. Open the Global Menu (
) and navigate to Control Panel → Instance Settings. Click Feature Flags under Platform, then click Beta, and toggle on Fragment Management API. Until this flag is enabled, the service calls below return 404 Not Found. Enabling a feature flag requires administrator access to the Liferay instance. -
Download and unzip Fragments API Basics.
curl https://resources.learn.liferay.com/examples/liferay-s2v4.zip -Ounzip liferay-s2v4.zip -
Find your site’s External Reference Code (ERC). The Fragment and Fragment Set endpoints address a site by its ERC. Use this value in each of the following service calls.
-
Navigate to the
curlfolder, and executeFragmentSets_POST_ToSites.shusing your site’s ERC as a parameter. This creates a new Fragment Set in the specified site.cd liferay-s2v4/curl./FragmentSets_POST_ToSites.sh [site-erc]The terminal displays the complete schema for the newly created Fragment Set:
{ "creator" : { ... }, "dateCreated" : "2026-07-01T14:00:00Z", "dateModified" : "2026-07-01T14:00:00Z", "description" : "This fragment set was created by the headless API.", "externalReferenceCode" : "able-fragment-set", "key" : "able-fragment-set", "marketplace" : false, "name" : "Able Fragment Set" } -
Copy the Fragment Set’s ERC. You use it throughout the rest of this tutorial.
The provided code uses basic authentication for demonstration purposes. For production, you should authorize users with OAuth2.
Examine the cURL Command
The FragmentSets_POST_ToSites.sh script calls the REST service with a cURL command.
curl \
"http://localhost:8080/o/headless-admin-fragment/v1.0/sites/${1}/fragment-sets" \
--data-raw '
{
"description": "This fragment set was created by the headless API.",
"key": "able-fragment-set",
"name": "Able Fragment Set"
}' \
--header "Content-Type: application/json" \
--request "POST" \
--user "test@liferay.com:learn"
The main arguments are
| Argument | Description |
|---|---|
--header "Content-Type: application/json" | Declares JSON as the request body format |
--request "POST" | The HTTP method to invoke at the specified endpoint |
"http://localhost:8080/o/headless-admin-fragment/v1.0/sites/${1}/fragment-sets" | The REST service endpoint for creating a Fragment Set in the specified site |
--data-raw '{...}' | The JSON body containing the Fragment Set’s properties |
--user "test@liferay.com:learn" | Basic authentication credentials |
The JSON body in --data-raw includes these parameters:
| Parameter | Description |
|---|---|
description | Text description of the Fragment Set |
key | Unique key for the Fragment Set, used internally |
name | Display name of the Fragment Set (required) |
See FragmentSetResource for service details.
Get a Fragment Set
Get a specific Fragment Set with the following cURL command. Replace [site-erc] and [fragment-set-erc] with your site’s and Fragment Set’s ERCs.
FragmentSets_GET_ByExternalReferenceCode.sh
Command:
./FragmentSets_GET_ByExternalReferenceCode.sh [site-erc] [fragment-set-erc]
Code:
curl \
"http://localhost:8080/o/headless-admin-fragment/v1.0/sites/${1}/fragment-sets/${2}" \
--user "test@liferay.com:learn"
The response matches the schema shown in the previous step, confirming the Fragment Set exists with the details you created.
Add a Fragment
A Fragment Set must exist before you can create a Fragment inside it. Because the Fragment Set is already identified by the URL, the request body omits any reference to it.
Every Fragment create or update requires a type of BasicFragment or FormFragment in the request body, and a Fragment’s type is fixed once it’s created. See Basic and Form Fragments.
-
Execute
Fragments_POST_ToFragmentSets.shusing the site’s ERC and the Fragment Set’s ERC as parameters. This creates a new Fragment inside the specified Fragment Set. The script uses the keycharlie-fragmentand name “Charlie Fragment.”./Fragments_POST_ToFragmentSets.sh [site-erc] [fragment-set-erc]The terminal displays the complete schema for the newly created Fragment:
{ "cacheable" : ..., "creator" : { ... }, "dateCreated" : "2026-07-01T14:05:00Z", "dateModified" : "2026-07-01T14:05:00Z", "externalReferenceCode" : "charlie-fragment", "fragmentVersions" : [ { "configuration" : "{\"fieldSets\":[]}", "css" : "", "html" : "<div>Charlie Fragment</div>", "js" : "", "status" : "Approved" } ], "icon" : "", "key" : "charlie-fragment", "marketplace" : false, "name" : "Charlie Fragment", "readOnly" : false, "type" : "BasicFragment" }NoteThe response includes
thumbnailURLReferenceonly when you request it with thenestedFieldsquery parameter, for examplehttp://localhost:8080/o/headless-admin-fragment/v1.0/sites/[site-erc]/fragments/[fragment-erc]?nestedFields=thumbnailURLReference. -
Copy the Fragment’s ERC. You use it with the Fragment services described in Fragment Services.
Examine the cURL Command
The Fragments_POST_ToFragmentSets.sh script calls the REST service with a cURL command.
curl \
"http://localhost:8080/o/headless-admin-fragment/v1.0/sites/${1}/fragment-sets/${2}/fragments" \
--data-raw '
{
"fragmentVersions": [
{
"configuration": "{\"fieldSets\":[]}",
"css": "",
"html": "<div>Charlie Fragment</div>",
"js": "",
"status": "Approved"
}
],
"key": "charlie-fragment",
"name": "Charlie Fragment",
"type": "BasicFragment"
}' \
--header "Content-Type: application/json" \
--request "POST" \
--user "test@liferay.com:learn"
This script follows the same argument pattern as FragmentSets_POST_ToSites.sh, but posts to "http://localhost:8080/o/headless-admin-fragment/v1.0/sites/${1}/fragment-sets/${2}/fragments". The site’s ERC and the Fragment Set’s ERC identify where the new Fragment is added. The JSON body includes these parameters:
| Parameter | Description |
|---|---|
fragmentVersions | At least one FragmentVersion with a status of Approved or Draft (required). Its configuration is a string containing serialized JSON, not a nested JSON object, so escape the quotes: "configuration": "{\"fieldSets\":[]}". When an Approved version’s configuration parses as a JSON object, Liferay validates it against the fragment configuration schema, whose only recognized root property is fieldSets. Use {"fieldSets":[]} when the Fragment has no configuration fields |
key | Unique key for the Fragment within the group. Liferay generates one from name when you omit it |
name | Display name of the Fragment (required) |
type | BasicFragment or FormFragment (required); see Basic and Form Fragments |
A Fragment’s html, css, js, and configuration values live in its fragmentVersions entries. A Fragment can carry a Draft version only, an Approved version only, or both at the same time. An update must carry at least one version, and it can’t drop the Approved version of a published Fragment, so resend the existing version in every update.
Fragment Services
The remaining Fragment sample files work like the Fragment Set services, identifying a Fragment by its site’s ERC and its own ERC. Run each one from the liferay-s2v4/curl folder, replacing [site-erc] with your site’s ERC and [fragment-erc] with the Fragment ERC you copied in the previous section.
./Fragments_GET_ByExternalReferenceCode.sh [site-erc] [fragment-erc]
./Fragments_PUT_ByExternalReferenceCode.sh [site-erc] [fragment-erc]
./Fragments_DELETE_ByExternalReferenceCode.sh [site-erc] [fragment-erc]
These calls take the Fragment’s ERC in the second position, not the Fragment Set’s.
| File | Description |
|---|---|
Fragments_GET_ByExternalReferenceCode.sh | Returns details for the specified Fragment. |
Fragments_PUT_ByExternalReferenceCode.sh | Updates the specified Fragment’s details. Renames it to “Dog Fragment,” resending its existing fragmentVersions entry unchanged, so the Fragment keeps its original “Charlie Fragment” content and only the name changes; the request must include at least one version, or the update fails. |
Fragments_DELETE_ByExternalReferenceCode.sh | Deletes the specified Fragment. A successful deletion returns an empty 204 No Content response. |
A few related capabilities exist in the API but aren’t included in the runnable sample project:
- Listing all Fragment Sets or Fragments in a site (
GET /sites/{siteExternalReferenceCode}/fragment-setsandGET /sites/{siteExternalReferenceCode}/fragments). - Creating a Fragment directly under a site, with the Fragment Set specified in the request body, instead of nested under a Fragment Set’s URL (
POST /sites/{siteExternalReferenceCode}/fragments). - Narrowing a site-level Fragment listing with a
filterquery parameter using OData filter syntax.
The API Explorer lists all FragmentSet and Fragment services and schemas and has an interface to try out each service.
Update a Fragment Set
Update an existing Fragment Set with the following cURL command. Replace [site-erc] and [fragment-set-erc] with your site’s and Fragment Set’s ERCs.
FragmentSets_PUT_ByExternalReferenceCode.sh
Command:
./FragmentSets_PUT_ByExternalReferenceCode.sh [site-erc] [fragment-set-erc]
Code:
curl \
"http://localhost:8080/o/headless-admin-fragment/v1.0/sites/${1}/fragment-sets/${2}" \
--data-raw '
{
"description": "This fragment set was updated by the headless API.",
"name": "Baker Fragment Set"
}' \
--header "Content-Type: application/json" \
--request "PUT" \
--user "test@liferay.com:learn"
The script renames the Fragment Set to “Baker Fragment Set”:
{
...
"name" : "Baker Fragment Set",
...
}
When the Fragment Set exists, only dateModified, description, and name are honored; any values sent for dateCreated, externalReferenceCode, key, and marketplace are ignored. When no Fragment Set matches the ERC you pass, this request creates one instead, applying key, marketplace, and dateCreated. Check the ERC carefully, since a typo produces a new Fragment Set rather than updating the one you meant. The Fragment Set’s external reference code always comes from the URL.
Delete a Fragment Set
Delete an existing Fragment Set with the following cURL command. Replace [site-erc] and [fragment-set-erc] with your site’s and Fragment Set’s ERCs.
FragmentSets_DELETE_ByExternalReferenceCode.sh
Command:
./FragmentSets_DELETE_ByExternalReferenceCode.sh [site-erc] [fragment-set-erc]
Code:
curl \
"http://localhost:8080/o/headless-admin-fragment/v1.0/sites/${1}/fragment-sets/${2}" \
--request "DELETE" \
--user "test@liferay.com:learn"
A successful deletion returns an empty 204 No Content response.
Basic and Form Fragments
A Fragment requires a type. The FragmentResource service distinguishes two Fragment subtypes:
BasicFragment: a JSON-configured Fragment. This tutorial’s sample cURL scripts create this type.FormFragment: adds afieldTypesarray that lists the input field types the form fragment collects. The available field types areBoolean,CAPTCHA,Date,DateTime,Email,File,FormButton,FriendlyURL,HTML,LocalizationSelect,LongText,Multiselect,Number,PhoneNumber,Relationship,Select,Stepper, andText.
Every Fragment create or update request sets type to BasicFragment or FormFragment. A Fragment’s type is fixed at creation, so to move a Fragment between the two subtypes, delete it and create it again.
This cURL example illustrates a FormFragment creation payload:
curl \
"http://localhost:8080/o/headless-admin-fragment/v1.0/sites/[site-erc]/fragment-sets/[fragment-set-erc]/fragments" \
--data-raw '
{
"key": "contact-form-fragment",
"name": "Contact Form Fragment",
"type": "FormFragment",
"fieldTypes": ["Text", "Email", "LongText"],
"fragmentVersions": [
{
"configuration": "{\"fieldSets\":[]}",
"css": "",
"html": "<form>...</form>",
"js": "",
"status": "Approved"
}
]
}' \
--header "Content-Type: application/json" \
--request "POST" \
--user "test@liferay.com:learn"
Additional Fragment Set Capabilities
A few related capabilities exist alongside the CRUD flow this tutorial demonstrates:
- Fragments installed from Liferay Marketplace appear in listings with
marketplace: true. Theirhtml,css,js, andconfigurationare withheld on read, so export and import cover the fragments you create. - Default (system) fragments are excluded entirely from listing and export/import.
- Fragment Compositions (fragments grouped and saved together as a single reusable unit) and fragments built with the deprecated Fragments Toolkit are out of scope for this API.
- Resource files and folders that belong to a Fragment Set, modeled on Documents and Media with support for nested folders, are a related capability not covered by this tutorial’s runnable example.
- You can export and import Fragment Sets across environments in bulk using Liferay’s Batch Engine. See Batch Engine API Basics: Importing Data and Batch Engine API Basics: Exporting Data.
Handling Errors
Calling the Fragment and Fragment Set services incorrectly returns an error message describing the problem:
| Situation | Error Message |
|---|---|
| Calling any of these endpoints before enabling the Fragment Management API beta feature flag | The request returns 404 Not Found. |
Creating a Fragment with POST /sites/{siteExternalReferenceCode}/fragments without specifying a Fragment Set in the request body | A fragment set external reference code is required to create a new fragment. |
Creating or updating a Fragment at /sites/{siteExternalReferenceCode}/fragments with a Fragment Set ERC that does not exist | No fragment set was found with external reference code {0}. |
Updating a Fragment without at least one FragmentVersion in the request body | At least one fragment entry version is required. |
Setting a published Fragment’s FragmentVersion status back to Draft | Unpublishing a fragment entry is not supported. |
Updating a Fragment with a type that differs from the one it was created with | The fragment type cannot be changed. |