Skip to main content

Document Service API

The Document Service API is built on top of the Query Engine API and is used to perform CRUD (create, retrieve, update, and delete) operations on documents .

The Document Service API also supports counting documents and, if Draft & Publish is enabled on the content-type, performing Strapi-specific operations such as publishing, unpublishing, and discarding drafts.

In Strapi 5, documents are uniquely identified by their documentId at the API level.

documentId explained: Replacing id from Strapi v4

In previous Strapi versions, the concept of id (used both in the Content API and as the database row identifier) was not always stable: a single entry could have multiple versions or localizations, and its numeric identifier id could change in cases such as duplication or import/export operations.

To address this limitation, Strapi 5 introduced documentId, a 24-character alphanumeric string, as a unique and persistent identifier for a content entry, independent of its physical records.

This new identifier is used internally in Strapi 5 to manage relationships, publishing, localization, and version history, as all possible variations of a content entry are now grouped under a single document concept.

As a result, starting with Strapi 5, many APIs and services rely on documentId instead of id to ensure consistency across operations. Some APIs may still return both documentId and id to ease the transition, but using documentId for content queries is strongly recommended, as documentId might be the only identifier used in future Strapi versions.

For more details on the transition from id to documentId, refer to the breaking change page and the migration guide from Entity Service to Document Service API.

Entity Service API is deprecated in Strapi 5

The Document Service API replaces the Entity Service API used in Strapi v4 (see Strapi v4 documentation).

Additional information on how to migrate from the Entity Service API to the Document Service API can be found in the migration reference.

Note

Relations can also be connected, disconnected, and set through the Document Service API, just like with the REST API (see the REST API relations documentation for examples).

Configuration

The documents.strictParams option enables strict validation of parameters passed to Document Service methods such as findMany and findOne. Configure it in the API configuration file (./config/api.js or ./config/api.ts). See the API configuration table for details on documents.strictParams.

Document objects

Document methods return a document object or a list of document objects, which represent a version of a content entry grouped under a stable documentId. Returned objects typically include:

  • documentId: Persistent identifier for the entry across locales and draft/published versions.
  • id: Database identifier for the specific locale/version record.
  • model fields: All fields defined in the content-type schema. Relations, components, and dynamic zones are not populated unless you opt in with populate (see Populating fields) or limit fields with fields (see Selecting fields).
  • metadata: publishedAt, createdAt, updatedAt, and createdBy/updatedBy when available.

Optionally, document objects can also include a status and locale property if Draft & Publish and Internationalization are enabled for the content-type.

Method overview

Each section below documents the parameters and examples for a specific method:

MethodPurpose
findOne()Fetch a document by documentId, optionally scoping to a locale or status.
findFirst()Return the first document that matches filters.
findMany()List documents with filters, sorting, and pagination.
create()Create a document, optionally targeting a locale.
update()Update a document by documentId.
delete()Delete a document or a specific locale version.
publish()Publish the draft version of a document.
unpublish()Move a published document back to draft.
discardDraft()Drop draft data and keep only the published version.
count()Count how many documents match the parameters.

findOne()

Syntax: findOne(parameters: Params) => Document

GETstrapi.documents().findOne()

Find a document matching the passed documentId and parameters. If only a documentId is passed without any other parameters, findOne() returns the draft version of a document in the default locale. Returns the matching document if found, otherwise returns null.

Parameters
documentId
ID
required
Document id
locale
String or undefined
optional
Locale of the document to find. Defaults to the default locale. See locale docs.
status
'published' | 'draft'
optional
If Draft & Publish is enabled: publication status. Can be published or draft. Default: draft. See status docs.
fields
Object
optional
Select fields to return. Defaults to all fields (except those not populated by default).
populate
Object
optional
Populate results with additional fields. Default: null.
GETstrapi.documents().findOne()
await strapi.documents('api::restaurant.restaurant').findOne({
documentId: 'a1b2c3d4e5f6g7h8i9j0klm'
})
200 OK
{
  "documentId": "a1b2c3d4e5f6g7h8i9j0klm",
  "name": "Biscotte Restaurant",
  "publishedAt": null,
  "locale": "en"
}

findFirst()

Syntax: findFirst(parameters: Params) => Document

GETstrapi.documents().findFirst()

Find the first document matching the parameters. By default, findFirst() returns the draft version, in the default locale, of the first document for the passed unique identifier (collection type id or single type id).

Parameters
locale
String or undefined
optional
Locale of the documents to find. Defaults to the default locale. See locale docs.
status
'published' | 'draft'
optional
If Draft & Publish is enabled: publication status. Can be published or draft. Default: draft. See status docs.
filters
Object
optional
Filters to use. Default: null.
fields
Object
optional
Select fields to return. Defaults to all fields (except those not populated by default).
populate
Object
optional
Populate results with additional fields. Default: null.

If no locale or status parameters are passed, results return the draft version for the default locale.

Generic exampleWith filters
GETstrapi.documents().findFirst()
await strapi.documents('api::restaurant.restaurant').findFirst()
200200
200 Generic
{
  "documentId": "a1b2c3d4e5f6g7h8i9j0klm",
  "name": "Restaurant Biscotte",
  "publishedAt": null,
  "locale": "en"
}

findMany()

Syntax: findMany(parameters: Params) => Document[]

GETstrapi.documents().findMany()

Find documents matching the parameters. When no parameter is passed, findMany() returns the draft version in the default locale for each document.

Parameters
locale
String or undefined
optional
Locale of the documents to find. Defaults to the default locale. See locale docs.
status
'published' | 'draft'
optional
If Draft & Publish is enabled: publication status. Can be published or draft. Default: draft. See status docs.
filters
Object
optional
Filters to use. Default: null.
fields
Object
optional
Select fields to return. Defaults to all fields (except those not populated by default).
populate
Object
optional
Populate results with additional fields. Default: null.
pagination
Object
optional
Paginate results.
sort
Object
optional
Sort results.

Available filters are detailed in the filters page of the Document Service API reference.

If no locale or status parameters are passed, results return the draft version for the default locale.

Generic exampleWith filters
GETstrapi.documents().findMany()
await strapi.documents('api::restaurant.restaurant').findMany()
200200
200 Generic
[
  {
    "documentId": "a1b2c3d4e5f6g7h8i9j0klm",
    "name": "Biscotte Restaurant",
    "publishedAt": null,
    "locale": "en"
  },
  {
    "documentId": "j9k8l7m6n5o4p3q2r1s0tuv",
    "name": "Pizzeria Arrivederci",
    "publishedAt": null,
    "locale": "en"
  }
]

create()

Syntax: create(parameters: Params) => Document

POSTstrapi.documents().create()

Create a new document. If no locale parameter is passed, create() creates the draft version of the document for the default locale.

Parameters
locale
String or undefined
optional
Locale of the document to create. Defaults to the default locale. See locale docs.
fields
Object
optional
Select fields to return. Defaults to all fields (except those not populated by default).
status
'published'
optional
If Draft & Publish is enabled: can be set to published to automatically publish the draft version of a document while creating it. See status docs.
populate
Object
optional
Populate results with additional fields. Default: null.
Tip

If the Draft & Publish feature is enabled on the content-type, you can automatically publish a document while creating it (see status documentation).

POSTstrapi.documents().create()
await strapi.documents('api::restaurant.restaurant').create({
data: {
  name: 'Restaurant B'
}
})
200 OK
{
  "documentId": "ln1gkzs6ojl9d707xn6v86mw",
  "name": "Restaurant B",
  "publishedAt": null,
  "locale": "en"
}

update()

Syntax: update(parameters: Params) => Promise<Document>

PUTstrapi.documents().update()

Update a document by documentId. If no locale parameter is passed, update() updates the document for the default locale.

Parameters
documentId
ID
required
Document id
locale
String or null
optional
Locale of the document to update. Defaults to the default locale. See locale docs.
filters
Object
optional
Filters to use. Default: null.
fields
Object
optional
Select fields to return. Defaults to all fields (except those not populated by default).
status
'published'
optional
If Draft & Publish is enabled: can be set to published to automatically publish the draft version of a document while updating it. See status docs.
populate
Object
optional
Populate results with additional fields. Default: null.
Tip

Published versions are read-only, so you can not technically update the published version of a document. To update a document and publish the new version right away, you can:

  • update its draft version with update(), then publish it with publish(),
  • or directly add status: 'published' along with the other parameters passed to update() (see status documentation).
Caution

It's not recommended to update repeatable components with the Document Service API (see the related breaking change entry for more details).

PUTstrapi.documents().update()
await strapi.documents('api::restaurant.restaurant').update({
  documentId: 'a1b2c3d4e5f6g7h8i9j0klm',
  data: { name: "New restaurant name" }
})
200 OK
{
  "documentId": "a1b2c3d4e5f6g7h8i9j0klm",
  "name": "New restaurant name",
  "locale": "en",
  "publishedAt": null
}

delete()

Syntax: delete(parameters: Params): Promise<{ documentId: ID, entries: Number }>

DELstrapi.documents().delete()

Delete a document or a specific locale version. If no locale parameter is passed, delete() only deletes the default locale version of a document. This deletes both the draft and published versions.

Parameters
documentId
ID
required
Document id
locale
String, '*', or null
optional
Locale version of the document to delete. Default: null (deletes only the default locale). See locale docs.
filters
Object
optional
Filters to use. Default: null.
fields
Object
optional
Select fields to return. Defaults to all fields (except those not populated by default).
populate
Object
optional
Populate results with additional fields. Default: null.
DELstrapi.documents().delete()
await strapi.documents('api::restaurant.restaurant').delete({
documentId: 'a1b2c3d4e5f6g7h8i9j0klm',
})
200 OK
{
  "documentId": "a1b2c3d4e5f6g7h8i9j0klm",
  "entries": [
    {
      "documentId": "a1b2c3d4e5f6g7h8i9j0klm",
      "name": "Biscotte Restaurant",
      "publishedAt": "2024-03-14T18:30:48.870Z",
      "locale": "en"
    }
  ]
}

publish()

Syntax: publish(parameters: Params): Promise<{ documentId: ID, entries: Number }>

PUTstrapi.documents().publish()

Publish the draft version of a document. This method is only available if Draft & Publish is enabled on the content-type. If no locale parameter is passed, publish() only publishes the default locale version of the document.

Parameters
documentId
ID
required
Document id
locale
String, '*', or null
optional
Locale of the documents to publish. Default: only the default locale. See locale docs.
filters
Object
optional
Filters to use. Default: null.
fields
Object
optional
Select fields to return. Defaults to all fields (except those not populated by default).
populate
Object
optional
Populate results with additional fields. Default: null.
PUTstrapi.documents().publish()
await strapi.documents('api::restaurant.restaurant').publish({
documentId: 'a1b2c3d4e5f6g7h8i9j0klm',
});
200 OK
{
  "documentId": "a1b2c3d4e5f6g7h8i9j0klm",
  "entries": [
    {
      "documentId": "a1b2c3d4e5f6g7h8i9j0klm",
      "name": "Biscotte Restaurant",
      "publishedAt": "2024-03-14T18:30:48.870Z",
      "locale": "en"
    }
  ]
}

unpublish()

Syntax: unpublish(parameters: Params): Promise<{ documentId: ID, entries: Number }>

PUTstrapi.documents().unpublish()

Move a published document back to draft. This method is only available if Draft & Publish is enabled on the content-type. If no locale parameter is passed, unpublish() only unpublishes the default locale version of the document.

Parameters
documentId
ID
required
Document id
locale
String, '*', or null
optional
Locale of the documents to unpublish. Default: only the default locale. See locale docs.
filters
Object
optional
Filters to use. Default: null.
fields
Object
optional
Select fields to return. Defaults to all fields (except those not populated by default).
populate
Object
optional
Populate results with additional fields. Default: null.
PUTstrapi.documents().unpublish()
await strapi.documents('api::restaurant.restaurant').unpublish({
documentId: 'a1b2c3d4e5f6g7h8i9j0klm'
});
200 OK
{
  "documentId": "lviw819d5htwvga8s3kovdij",
  "entries": [
    {
      "documentId": "lviw819d5htwvga8s3kovdij",
      "name": "Biscotte Restaurant",
      "publishedAt": null,
      "locale": "en"
    }
  ]
}

discardDraft()

Syntax: discardDraft(parameters: Params): Promise<{ documentId: ID, entries: Number }>

PUTstrapi.documents().discardDraft()

Drop draft data and keep only the published version. This method is only available if Draft & Publish is enabled on the content-type. If no locale parameter is passed, discardDraft() discards draft data and overrides it with the published version only for the default locale.

Parameters
documentId
ID
required
Document id
locale
String, '*', or null
optional
Locale of the documents to discard. Default: only the default locale. See locale docs.
filters
Object
optional
Filters to use. Default: null.
fields
Object
optional
Select fields to return. Defaults to all fields (except those not populated by default).
populate
Object
optional
Populate results with additional fields. Default: null.
PUTstrapi.documents().discardDraft()
strapi.documents.discardDraft({
documentId: 'a1b2c3d4e5f6g7h8i9j0klm',
});
200 OK
{
  "documentId": "lviw819d5htwvga8s3kovdij",
  "entries": [
    {
      "documentId": "lviw819d5htwvga8s3kovdij",
      "name": "Biscotte Restaurant",
      "publishedAt": null,
      "locale": "en"
    }
  ]
}

count()

Syntax: count(parameters: Params) => number

GETstrapi.documents().count()

Count how many documents match the parameters. If no parameter is passed, the count() method returns the total number of documents for the default locale.

Parameters
locale
String or null
optional
Locale of the documents to count. Defaults to the default locale. See locale docs.
status
'published' | 'draft'
optional
If Draft & Publish is enabled: publication status. published to count only published documents, draft to count draft documents (returns all documents). Default: draft. See status docs.
filters
Object
optional
Filters to use. Default: null.
Note

Since published documents necessarily also have a draft counterpart, a published document is still counted as having a draft version.

This means that counting with the status: 'draft' parameter still returns the total number of documents matching other parameters, even if some documents have already been published and are not displayed as "draft" or "modified" in the Content Manager anymore. There currently is no way to prevent already published documents from being counted.

Generic exampleCount publishedWith filters
GETstrapi.documents().count()
await strapi.documents('api::restaurant.restaurant').count()