Documents
middlewares
middlewares
Type
External
Status
Published
Created
Mar 5, 2026
Updated
Mar 5, 2026

Document Service API: Middlewares#

The Document Service API offers the ability to extend its behavior thanks to middlewares.

Document Service middlewares allow you to perform actions before and/or after a method runs.

Simplified Strapi backend diagram with controllers highlighted The diagram represents a simplified version of how a request travels through the Strapi back end, with the Document Service highlighted. The backend customization introduction page includes a complete, interactive diagram.

Registering a middleware#

Syntax: strapi.documents.use(middleware)

Parameters#

A middleware is a function that receives a context and a next function.

Syntax: (context, next) => ReturnType<typeof next>

ParameterDescriptionType
contextMiddleware contextContext
nextCall the next middleware in the stackfunction

context#

ParameterDescriptionType
actionThe method that is running (see available methods)string
paramsThe method params (see available methods)Object
uidContent type unique identifierstring
contentTypeContent typeContentType
Examples:

The following examples show what context might include depending on the method called:

{
  uid: "api::restaurant.restaurant",
  contentType: {
    kind: "collectionType",
    collectionName: "restaurants",
    info: {
      singularName: "restaurant",
      pluralName: "restaurants",
      displayName: "restaurant"
    },
    options: {
      draftAndPublish: true
    },
    pluginOptions: {},
    attributes: {
      name: { /*...*/ },
      description: { /*...*/ },
      createdAt: { /*...*/ },
      updatedAt: { /*...*/ },
      publishedAt: { /*...*/ },
      createdBy: { /*...*/ },
      updatedBy: { /*...*/ },
      locale: { /*...*/ },
    },
    apiName: "restaurant",
    globalId: "Restaurants",
    uid: "api::restaurant.restaurant",
    modelType: "contentType",
    modelName: "restaurant",
    actions: { /*...*/ },
    lifecycles: { /*...*/ },
  },
  action: "findOne",
  params: {
    documentId: 'hp7hjvrbt8rcgkmabntu0aoq',
    locale: undefined,
    status: "publish"
    populate: { /*...*/ },
  }
}
{
  uid: "api::restaurant.restaurant",
  contentType: {
    kind: "collectionType",
    collectionName: "restaurants",
    info: {
      singularName: "restaurant",
      pluralName: "restaurants",
      displayName: "restaurant"
    },
    options: {
      draftAndPublish: true
    },
    pluginOptions: {},
    attributes: {
      name: { /*...*/ },
      description: { /*...*/ },
      createdAt: { /*...*/ },
      updatedAt: { /*...*/ },
      publishedAt: { /*...*/ },
      createdBy: { /*...*/ },
      updatedBy: { /*...*/ },
      locale: { /*...*/ },
    },
    apiName: "restaurant",
    globalId: "Restaurants",
    uid: "api::restaurant.restaurant",
    modelType: "contentType",
    modelName: "restaurant",
    actions: { /*...*/ },
    lifecycles: { /*...*/ },
  },
  action: "findMany",
  params: {
    filters: { /*...*/ },
    status: "draft",
    locale: null,
    fields: ['name', 'description'],
  }
}
{
  uid: "api::restaurant.restaurant",
  contentType: {
    kind: "collectionType",
    collectionName: "restaurants",
    info: {
      singularName: "restaurant",
      pluralName: "restaurants",
      displayName: "restaurant"
    },
    options: {
      draftAndPublish: true
    },
    pluginOptions: {},
    attributes: {
      name: { /*...*/ },
      description: { /*...*/ },
      createdAt: { /*...*/ },
      updatedAt: { /*...*/ },
      publishedAt: { /*...*/ },
      createdBy: { /*...*/ },
      updatedBy: { /*...*/ },
      locale: { /*...*/ },
    },
    apiName: "restaurant",
    globalId: "Restaurants",
    uid: "api::restaurant.restaurant",
    modelType: "contentType",
    modelName: "restaurant",
    actions: { /*...*/ },
    lifecycles: { /*...*/ },
  },
  action: "create",
  params: {
    data: { /*...*/ },
    status: "draft",
    populate: { /*...*/ },
  }
}
{
  uid: "api::restaurant.restaurant",
  contentType: {
    kind: "collectionType",
    collectionName: "restaurants",
    info: {
      singularName: "restaurant",
      pluralName: "restaurants",
      displayName: "restaurant"
    },
    options: {
      draftAndPublish: true
    },
    pluginOptions: {},
    attributes: {
      name: { /*...*/ },
      description: { /*...*/ },
      createdAt: { /*...*/ },
      updatedAt: { /*...*/ },
      publishedAt: { /*...*/ },
      createdBy: { /*...*/ },
      updatedBy: { /*...*/ },
      locale: { /*...*/ },
    },
    apiName: "restaurant",
    globalId: "Restaurants",
    uid: "api::restaurant.restaurant",
    modelType: "contentType",
    modelName: "restaurant",
    actions: { /*...*/ },
    lifecycles: { /*...*/ },
  },
  action: "update",
  params: {
    data: { /*...*/ },
    documentId: 'hp7hjvrbt8rcgkmabntu0aoq',
    locale: undefined,
    status: "draft"
    populate: { /*...*/ },
  }
}
{
  uid: "api::restaurant.restaurant",
  contentType: {
    kind: "collectionType",
    collectionName: "restaurants",
    info: {
      singularName: "restaurant",
      pluralName: "restaurants",
      displayName: "restaurant"
    },
    options: {
      draftAndPublish: true
    },
    pluginOptions: {},
    attributes: {
      name: { /*...*/ },
      description: { /*...*/ },
      createdAt: { /*...*/ },
      updatedAt: { /*...*/ },
      publishedAt: { /*...*/ },
      createdBy: { /*...*/ },
      updatedBy: { /*...*/ },
      locale: { /*...*/ },
    },
    apiName: "restaurant",
    globalId: "Restaurants",
    uid: "api::restaurant.restaurant",
    modelType: "contentType",
    modelName: "restaurant",
    actions: { /*...*/ },
    lifecycles: { /*...*/ },
  },
  action: "delete",
  params: {
    data: { /*...*/ },
    documentId: 'hp7hjvrbt8rcgkmabntu0aoq',
    locale: "*",
    populate: { /*...*/ },
  }
}

next#

next is a function without parameters that calls the next middleware in the stack and return its response.

Example

strapi.documents.use((context, next) => {
  return next();
});

Where to register#

Generaly speaking you should register your middlewares during the Strapi registration phase.

Users#

The middleware must be registered in the general register() lifecycle method:

module.exports = {
  register({ strapi }) {
    strapi.documents.use((context, next) => {
      // your logic
      return next();
    });
  },

  // bootstrap({ strapi }) {},
  // destroy({ strapi }) {},
};

Plugin developers#

The middleware must be registered in the plugin's register() lifecycle method:

module.exports = {
  register({ strapi }) {
    strapi.documents.use((context, next) => {
      // your logic
      return next();
    });
  },

  // bootstrap({ strapi }) {},
  // destroy({ strapi }) {},
};

Implementing a middleware#

When implementing a middleware, always return the response from next().
Failing to do this will break the Strapi application.

Examples#

const applyTo = ['api::article.article'];

strapi.documents.use((context, next) => {
  // Only run for certain content types
  if (!applyTo.includes(context.uid)) {
    return next();
  }

  // Only run for certain actions
  if (['create', 'update'].includes(context.action)) {
    context.params.data.fullName = `${context.params.data.firstName} ${context.params.data.lastName}`;
  }

  const result = await next();

  // do something with the result before returning it
  return result
});

:::strapi Lifecycle hooks
The Document Service API triggers various database lifecycle hooks based on which method is called. For a complete reference, see Document Service API: Lifecycle hooks.
:::