Document API Basics
Liferay’s headless delivery application provides REST services for Documents and Media that add documents and folders, list their information, modify them, delete them, and more. You can call those services using cURL commands and Java classes.
Liferay DXP 2024.Q4+/Portal GA129+ The Documents API now uses External Reference Codes (ERCs) to reference document entries, folders, types, metadata sets, and shortcuts, enabling consistent identification across instances and supporting batch export/import for improved content management and portability.
Start with uploading documents using an example cURL command and Java class.
Post a Document
Start a new Liferay instance by running
docker run -it -m 8g -p 8080:8080 liferay/portal:7.4.3.132-ga132
Sign in to Liferay at http://localhost:8080. Use the email address test@liferay.com and the password test. When prompted, change the password to learn.
When signed in, retrieve the site’s ID. Use this ID in several service calls.
Then, follow these steps:
-
Download and unzip the example project:
curl https://resources.learn.liferay.com/examples/liferay-g9i6.zip -Ounzip liferay-g9i6.zip
Use a cURL script to upload a file to Documents and Media.
-
On the command line, navigate to the
curlfolder.cd liferay-g9i6.zip/curl -
Upload a file by executing the
Documents_POST_ToSites.shscript with your site ID as a parameter. For example,./Documents_POST_ToSites.sh 1234NoteIf your user and password aren’t
test@liferay.comandlearn, respectively, replace those values in theDocuments_POST_ToSites.shscript before running it.
The script uploads itself to your site’s Documents and Media.

The command response describes the new Documents and Media file in JSON, like this:
{
...
"description": "",
...
"id": 38301,
...
"title": "Documents_POST_ToSites.sh"
}
The response includes the file’s description, newly assigned ID, title, and more. Note the id value for later commands.
Next, use a Java class to upload a file.
-
Go to the
javafolder and compile the Java source files.cd ../javajavac -classpath .:* *.java -
Upload a file to Documents and Media by running the
Documents_POST_ToSitesclass below, replacing thesiteIdsystem property value with your site’s ID.java -classpath .:* -DsiteId=1234 Documents_POST_ToSitesNoteIf your user and password aren’t
test@liferay.comandtest, respectively, replace those values in theDocuments_POST_ToSites.javafile and recompile the class before running it.
The class uploads its source file Documents_POST_ToSites.java to Documents and Media.

Read on to see how the cURL command and Java class work.
Examine the cURL Command
The Documents_POST_ToSites.sh script uploads a file by calling a headless-delivery application REST service with cURL.
curl \
"http://localhost:8080/o/headless-delivery/v1.0/sites/${1}/documents" \
--form "file=@Document_POST_ToSite.sh" \
--header "Content-Type: multipart/form-data" \
--request "POST" \
--user "test@liferay.com:learn"
Here are the command’s arguments:
| Arguments | Description |
|---|---|
-F "file=@Documents_POST_ToSites.sh" | The file to post. |
-H "Content-Type: multipart/form-data" | The media type (MIME type) being posted. |
-X POST | The HTTP method to invoke at the specified endpoint. |
"http://localhost:8080/o/headless-delivery/v1.0/sites/${1}/documents" | The REST service endpoint. Your site ID parameter replaces ${1}. |
-u "test@liferay.com:learn" | Basic authentication credentials. |
Basic authentication is used here for demonstration purposes. For production, you should authorize users via OAuth 2.0. See Using OAuth2 to Authorize Users for a sample React application that uses OAuth2.
Other cURL commands for the Document and DocumentFolder REST services use similar arguments.
Next, see how similar the Java call is.
Examine the Java Class
The Documents_POST_ToSites.java class uploads a file by calling a headless-delivery application REST service.
public static void main(String[] args) throws Exception {
DocumentResource.Builder builder = DocumentResource.builder();
DocumentResource documentResource = builder.authentication(
"test@liferay.com", "learn"
).build();
System.out.println(
documentResource.postSiteDocument(
Long.valueOf(System.getProperty("siteId")), new Document(),
new HashMap<String, File>() {
{
put("file", new File("Documents_POST_ToSites.java"));
}
}));
}
This class invokes the REST service using only three lines of code:
| Line (abbreviated) | Description |
|---|---|
DocumentResource.Builder builder = ... | Gets a Builder for generating a DocumentResource service instance. |
DocumentResource documentResource = builder.authentication(...).build(); | Specifies basic authentication and generates a DocumentResource service instance. |
Document document = documentResource.postSiteDocument(...); | Calls the DocumentResource.postSiteDocument method, passing in a site ID, a Document object to represent the uploaded file, and a hash map that specifies the file to upload. The file is arbitrary–this example uses the local file Documents_POST_ToSites.java for convenience. |
Note that the project includes the com.liferay.headless.delivery.client.jar file as a dependency. You can find client JAR dependency information for all REST applications in the API explorer in your installation at /o/api.
The main method’s comment demonstrates running the class.
The other example Java classes are similar to this one, but call different DocumentResource methods.
See DocumentResource for service details.
Below are examples of calling other Document REST services using cURL and Java.
Get Site Documents
You can list a site’s documents by executing the following cURL or Java command. As above, replace 1234 with your site’s ID.
Documents_GET_FromSites.sh
Command:
./Documents_GET_FromSites.sh 1234
Code:
curl \
"http://localhost:8080/o/headless-delivery/v1.0/sites/${1}/documents" \
--user "test@liferay.com:learn"
Documents_GET_FromSites.java
Command:
java -classpath .:* -DsiteId=1234 Documents_GET_FromSites
Code:
public static void main(String[] args) throws Exception {
DocumentResource.Builder builder = DocumentResource.builder();
DocumentResource documentResource = builder.authentication(
"test@liferay.com", "learn"
).build();
System.out.println(
documentResource.getSiteDocumentsPage(
Long.valueOf(System.getProperty("siteId")), null, null, null,
null, Pagination.of(1, 2), null));
}
The site’s Document objects are included in the JSON response.
{
"actions": {
"updateBatch": {
"method": "PUT",
"href": "http://localhost:8080/o/headless-delivery/v1.0/documents/batch"
},
"get": {
"method": "GET",
"href": "http://localhost:8080/o/headless-delivery/v1.0/sites/1234/documents"
},
"create": {
"method": "POST",
"href": "http://localhost:8080/o/headless-delivery/v1.0/sites/1234/documents"
},
"createBatch": {
"method": "POST",
"href": "http://localhost:8080/o/headless-delivery/v1.0/sites/1234/documents/batch"
},
"deleteBatch": {
"method": "DELETE",
"href": "http://localhost:8080/o/headless-delivery/v1.0/documents/batch"
}
},
"facets": [],
"items": [
{
"actions": {
"get-rendered-content-by-display-page": {
"method": "GET",
"href": "http://localhost:8080/o/headless-delivery/v1.0/documents/32131/rendered-content-by-display-page/{displayPageKey}"
},
"get": {
"method": "GET",
"href": "http://localhost:8080/o/headless-delivery/v1.0/documents/32131"
},
"replace": {
"method": "PUT",
"href": "http://localhost:8080/o/headless-delivery/v1.0/documents/32131"
},
"update": {
"method": "PATCH",
"href": "http://localhost:8080/o/headless-delivery/v1.0/documents/32131"
},
"delete": {
"method": "DELETE",
"href": "http://localhost:8080/o/headless-delivery/v1.0/documents/32131"
}
},
"adaptedImages": [
{
"contentUrl": "/o/adaptive-media/image/32131/Preview-1000x0/seahorse.jpg?t=1715340699885",
"height": 1510,
"resolutionName": "Preview-1000x0",
"sizeInBytes": 127254,
"width": 1000
},
{
"contentUrl": "/o/adaptive-media/image/32131/Thumbnail-300x300/seahorse.jpg?t=1715340699885",
"height": 300,
"resolutionName": "Thumbnail-300x300",
"sizeInBytes": 10927,
"width": 199
}
],
"contentUrl": "/documents/1234/0/seahorse.jpg/4be7d2ff-b9ac-a7ab-1081-537536ece7d9?version=1.0&t=1715340699885&download=true",
"creator": {
"additionalName": "",
"contentType": "UserAccount",
"familyName": "Test",
"givenName": "Test",
"id": 20122,
"name": "Test Test"
},
"customFields": [],
"dateCreated": "2024-05-10T11:29:14Z",
"dateModified": "2024-05-10T11:31:39Z",
"description": "",
"documentFolderId": 0,
"documentType": {
"availableLanguages": [],
"contentFields": [],
"description": "",
"name": "Basic Document"
},
"encodingFormat": "image/jpeg",
"externalReferenceCode": "4be7d2ff-b9ac-a7ab-1081-537536ece7d9",
"fileExtension": "jpg",
"fileName": "seahorse.jpg",
"friendlyUrlPath": "seahorse-friendly-url",
"id": 32131,
"keywords": [],
"numberOfComments": 0,
"relatedContents": [],
"renderedContents": [],
"siteId": 1234,
"sizeInBytes": 792227,
"taxonomyCategoryBriefs": [],
"title": "seahorse"
}
],
"lastPage": 1,
"page": 1,
"pageSize": 20,
"totalCount": 1
}
From the response, you can extract several pieces of information such as
-
A list of actions that can be performed on the document, including getting, updating, replacing, or deleting.
-
The document’s
contentUrlfor accessing the document content. -
Information about the document’s
creator, including name and ID. -
The
dateCreatedanddateModifiedtimestamps that indicate when the document was created and last modified, respectively. -
Liferay DXP 2024.Q2+/Portal GA120+
The document's [friendlyUrlPath](../../../digital-asset-management/uploading-and-managing/configuring-document-urls.md) that can be the file’s name or a customized value set by the user.
Get a Document
You can get a Document’s fields by executing the following cURL or Java command. Replace 1234 with the Document’s ID.
Use Documents_GET_FromSites.[java|sh] to get site Document IDs.
Documents_GET_ById.sh
Command:
./Documents_GET_ById.sh 1234
Code:
curl \
"http://localhost:8080/o/headless-delivery/v1.0/documents/${1}" \
--user "test@liferay.com:learn"
Documents_GET_ById.java
Command:
java -classpath .:* -DdocumentId=1234 Documents_GET_ById
Code:
public static void main(String[] args) throws Exception {
DocumentResource.Builder builder = DocumentResource.builder();
DocumentResource documentResource = builder.authentication(
"test@liferay.com", "learn"
).build();
System.out.println(
documentResource.getDocument(
Long.valueOf(System.getProperty("documentId"))));
}
The Document fields are included in the JSON response.
Get Document Content
Document content is encoded in Base64 and embedded in the Document’s nestedFields. You can get the content by executing the following cURL or Java command. Replace 1234 with the Document’s ID.
Documents_GET_ContentValue_ById.sh
Command:
./Documents_GET_ContentValue_ById.sh 1234
Code:
curl \
"http://localhost:8080/o/headless-delivery/v1.0/documents/${1}?nestedFields=contentValue&fields=contentValue" \
--user "test@liferay.com:learn" \
| sed -n "2 p" \
| awk -F ":" '{print $2}' \
| tr -d " \"" \
| base64 -d
The first argument line specifies the service endpoint and authentication credentials, respectively. The URL’s /o/headless-delivery/v1.0/documents/${1} part is the REST service endpoint to get the Document by its ID. This URL is the same as the Documents_GET_ById.sh script’s URL. The ?nestedFields=contentValue part requests the contentValue embedded in the Document’s nestedFields. Lastly the &fields=contentValue part filters on the contentValue field, so that the content field alone is returned. Invoking only the service, however, returns Base64-encoded content wrapped in JSON, like this:
{
"contentValue" : "Y3VybCBcCgktRiAiZmlsZT1ARG9jdW1lbnRfUE9TVF9Ub1NpdGUuc2giIFwKCS1IICJDb250ZW50LVR5cGU6IG11bHRpcGFydC9mb3JtLWRhdGEiIFwKCS1YIFBPU1QgXAoJImh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9vL2hlYWRsZXNzLWRlbGl2ZXJ5L3YxLjAvc2l0ZXMvJHsxfS9kb2N1bWVudHMiIFwKCS11ICJ0ZXN0QGxpZmVyYXkuY29tOnRlc3Qi"
}
The routines following the service invocation process the encoded content. The sed and awk routines isolate the Document content value and the tr routine decodes it. Here’s the decoded content returned for the Documents_POST_ToSites.sh Document that you uploaded:
curl \
"http://localhost:8080/o/headless-delivery/v1.0/documents/${1}?nestedFields=contentValue&fields=contentValue" \
--user "test@liferay.com:learn" \
| sed -n "2 p" \
| awk -F ":" '{print $2}' \
| tr -d " \"" \
| base64 -d
Documents_GET_ContentValue_ById.java
The Java code to get Document content and decode it is simpler than the previous cURL command.
Command:
java -classpath .:* -DdocumentId=1234 Documents_GET_ContentValue_ById
Code:
public static void main(String[] args) throws Exception {
DocumentResource.Builder builder = DocumentResource.builder();
builder.parameter("nestedFields", "contentValue");
DocumentResource documentResource = builder.authentication(
"test@liferay.com", "learn"
).build();
System.out.println(
new String(
Base64.getDecoder(
).decode(
documentResource.getDocument(
Long.valueOf(System.getProperty("documentId"))
).getContentValue()
)));
}
Most of the code resembles the code in Documents_POST_ToSites.java. There are a couple key differences.
The following line adds the contentValue nested field as a request parameter.
builder.parameter("nestedFields", "contentValue");
After getting the Document by its ID, a Base64.Decoder decodes the Document’s content.
Base64.Decoder decoder = Base64.getDecoder();
Patch a Document
Document’s PATCH services update a Document and its fields. You can update a Document by executing the following cURL or Java command. Replace 1234 with the Document’s ID.
Documents_PATCH_ById.sh
Command:
./Documents_PATCH_ById.sh 1234
Code:
curl \
"http://localhost:8080/o/headless-delivery/v1.0/documents/${1}" \
--form "document={\"description\": \"Bar\"}" \
--form "file=@Document_POST_ToSite.sh" \
--header "Content-Type: multipart/form-data; boundary=ARBITRARY" \
--request "PATCH" \
--user "test@liferay.com:learn"
The first form data part (following -F) specifies a new value for the Document’s description field. The second form data part specifies the updated file to upload. Note, both are not required. You can patch only the file or only the document’s metadata.
Documents_PATCH_ById.java
Command:
java -classpath .:* -DdocumentId=1234 Documents_PATCH_ById
Code:
public static void main(String[] args) throws Exception {
DocumentResource.Builder builder = DocumentResource.builder();
DocumentResource documentResource = builder.authentication(
"test@liferay.com", "learn"
).build();
System.out.println(
documentResource.patchDocument(
Long.valueOf(System.getProperty("documentId")),
new Document() {
{
description = "Bar";
}
},
new HashMap<String, File>() {
{
put("file", new File("Document_POST_ToSite.java"));
}
}));
}
The Java code above calls DocumentResource’s patchDocument method, passing in the Document’s ID, a Document object that includes a field to update, and the updated file to upload.
The above commands update the Document’s description to “Bar”.

Put a Document
Document’s PUT services replace the Document and its fields entirely. You can replace a Document by executing the following cURL or Java command. Replace 1234 with the Document’s ID.
Documents_PUT_ById.sh
Command:
./Documents_PUT_ById.sh 1234
Code:
curl \
"http://localhost:8080/o/headless-delivery/v1.0/documents/${1}" \
--form "document={\"description\": \"Goo\", \"title\": \"Document_PUT_ById.sh\"}" \
--form "file=@Document_PUT_ById.sh" \
--header "Content-Type: multipart/form-data; boundary=ARBITRARY" \
--request "PUT" \
--user "test@liferay.com:learn"
The first form data part sets new description and title field values. The second form data part specifies a replacement file to upload.
Documents_PUT_ById.java
Command:
java -classpath .:* -DdocumentId=1234 Documents_PUT_ById
Code:
public static void main(String[] args) throws Exception {
DocumentResource.Builder builder = DocumentResource.builder();
DocumentResource documentResource = builder.authentication(
"test@liferay.com", "learn"
).build();
System.out.println(
documentResource.putDocument(
Long.valueOf(System.getProperty("documentId")),
new Document() {
{
description = "Goo";
title = "Documents_PUT_ById.java";
}
},
new HashMap<String, File>() {
{
put("file", new File("Documents_PUT_ById.java"));
}
}));
}
The Java code above calls DocumentResource’s putDocument method, passing in the Document’s ID, a Document object that includes values for the Document’s description and title fields, and a replacement file to upload.
The above cURL command and Java class replace Document instances with completely new ones that have the new titles Documents_PUT_ById.sh and Documents_PUT_ById.java, respectively, and have the description Goo.
Unless you want to use the current Document’s title, make sure to specify the title value you want for the replacement Document.

Delete a Document
You can delete a Document by executing the following cURL or Java command. Replace 1234 with the Document’s ID.
Documents_DELETE_ById.sh
Command:
./Documents_DELETE_ById.sh 1234
Code:
curl \
"http://localhost:8080/o/headless-delivery/v1.0/documents/${1}" \
--request "DELETE" \
--user "test@liferay.com:learn"
Documents_DELETE_ById.java
Command
java -classpath .:* -DdocumentId=1234 Documents_DELETE_ById
Code:
public static void main(String[] args) throws Exception {
DocumentResource.Builder builder = DocumentResource.builder();
DocumentResource documentResource = builder.authentication(
"test@liferay.com", "learn"
).build();
documentResource.deleteDocument(
Long.valueOf(System.getProperty("documentId")));
}
The Documents are removed from Documents and Media.
More Document and Document Folder Services
The following cURL commands and Java classes demonstrate more Document services and DocumentFolder services.
| Files | Description |
|---|---|
Documents_POST_ToDocumentFolders.[java\|sh] | Posts a document to a folder. |
DocumentFolders_GET_ById.[java\|sh] | Lists a folder’s fields. |
DocumentFolders_PATCH_ById.[java\|sh] | Updates a folder and its fields. |
DocumentFolders_POST_ToSites.[java\|sh] | Posts a document folder to a site. |
DocumentFolders_PUT_ById.[java\|sh] | Replaces a folder and its fields entirely. |
DocumentFolders_DELETE_ById.[java\|sh] | Deletes a document folder. |
DocumentFolders_GET_FromSites.[java\|sh] | Lists a site’s folders. |
The API Explorer lists all of the Document and DocumentFolder services and schemas, and has an interface to try out each service.
See the DocumentResource and DocumentFolderResource Java interfaces too.