Content Management APIs

Fragments API Basics

Beta Feature

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.

Important

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:

  1. Enable the Fragment Management API beta feature flag. Open the Global Menu (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.

  2. Download and unzip Fragments API Basics.

    curl https://resources.learn.liferay.com/examples/liferay-s2v4.zip -O
    
    unzip liferay-s2v4.zip
    
  3. 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.

  4. Navigate to the curl folder, and execute FragmentSets_POST_ToSites.sh using 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"
    }
    
  5. Copy the Fragment Set’s ERC. You use it throughout the rest of this tutorial.

Important

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

ArgumentDescription
--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:

ParameterDescription
descriptionText description of the Fragment Set
keyUnique key for the Fragment Set, used internally
nameDisplay name of the Fragment Set (required)
Important

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.

Important

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.

  1. Execute Fragments_POST_ToFragmentSets.sh using 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 key charlie-fragment and 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"
    }
    
    Note

    The response includes thumbnailURLReference only when you request it with the nestedFields query parameter, for example http://localhost:8080/o/headless-admin-fragment/v1.0/sites/[site-erc]/fragments/[fragment-erc]?nestedFields=thumbnailURLReference.

  2. 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:

ParameterDescription
fragmentVersionsAt 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
keyUnique key for the Fragment within the group. Liferay generates one from name when you omit it
nameDisplay name of the Fragment (required)
typeBasicFragment 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.

FileDescription
Fragments_GET_ByExternalReferenceCode.shReturns details for the specified Fragment.
Fragments_PUT_ByExternalReferenceCode.shUpdates 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.shDeletes 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-sets and GET /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 filter query 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",
  ...
}
Important

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 a fieldTypes array that lists the input field types the form fragment collects. The available field types are Boolean, CAPTCHA, Date, DateTime, Email, File, FormButton, FriendlyURL, HTML, LocalizationSelect, LongText, Multiselect, Number, PhoneNumber, Relationship, Select, Stepper, and Text.
Important

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. Their html, css, js, and configuration are 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:

SituationError Message
Calling any of these endpoints before enabling the Fragment Management API beta feature flagThe request returns 404 Not Found.
Creating a Fragment with POST /sites/{siteExternalReferenceCode}/fragments without specifying a Fragment Set in the request bodyA 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 existNo fragment set was found with external reference code {0}.
Updating a Fragment without at least one FragmentVersion in the request bodyAt least one fragment entry version is required.
Setting a published Fragment’s FragmentVersion status back to DraftUnpublishing a fragment entry is not supported.
Updating a Fragment with a type that differs from the one it was created withThe fragment type cannot be changed.