Skip to main content

Server API for plugins: An overview

Page summary:

The Server API defines what a plugin registers, exposes, and executes on the Strapi server. It covers lifecycle hooks, routes, controllers, services, policies, middlewares, and configuration. Use the entry file to declare what the plugin contributes, then navigate to the dedicated pages below for each capability.

A Strapi plugin can interact with both the back end and the front end of a Strapi application. The Server API covers the back-end part: it defines what the plugin registers, exposes, and executes on the Strapi server. The server part is defined in the entry file, which exports an object (or a function returning an object). That object describes what the plugin contributes to the server.

For more information on how plugins can customize the admin panel UI, see Admin Panel API.

Prerequisites

Before diving deeper into the concepts on this page, please ensure you created a Strapi plugin.

Entry file​

The entry file for the Server API is [plugin-name]/server/src/index.js|ts. This file exports the required interface, with the following parameters available:

Parameter typeAvailable parameters
Lifecycle functionsregister(), bootstrap(), destroy()
Configurationconfig object
Backend customizationscontentTypes, routes, controllers, services, policies, middlewares

A minimal entry file looks like this:

/src/plugins/my-plugin/server/src/index.js
'use strict';

const register = require('./register');
const bootstrap = require('./bootstrap');
const destroy = require('./destroy');
const config = require('./config');
const contentTypes = require('./content-types');
const routes = require('./routes');
const controllers = require('./controllers');
const services = require('./services');
const policies = require('./policies');
const middlewares = require('./middlewares');

module.exports = () => ({
register,
bootstrap,
destroy,
config,
contentTypes,
routes,
controllers,
services,
policies,
middlewares,
});

All server code can technically live in the single entry file, but splitting each concern into its own folder, as generated by the Plugin SDK, is strongly recommended. The examples in this documentation follow that structure.

Notes
  • The entry file accepts either an object literal or a function that returns the same object shape. When the function form is used, Strapi calls it with { env } (not { strapi }) while loading the plugin module.
  • config is a configuration object, not an executable lifecycle hook. Unlike register(), bootstrap(), or destroy(), it is not called as a function during the plugin lifecycle. It is loaded at startup and used to set defaults and validate user configuration. See server lifecycle for more information.

Available actions​

The Server API lets a plugin take advantage of several building blocks to define its server-side behavior.

Use the following table to find which capability matches your goal:

GoalParameter to useWhen it runs
Run code before the server startsregister()Before database and routing initialization
Run code after all plugins are loadedbootstrap()After database, routes, and permissions are initialized
Clean up resources on shutdowndestroy()On shutdown
Define plugin options with defaults and validationconfigLoaded at startup
Declare plugin content-typescontentTypesLoaded at startup
Expose HTTP endpointsroutesLoaded at startup
Handle HTTP requestscontrollersCalled per request
Implement business logicservicesCalled from controllers or lifecycle hooks
Enforce access rules on routespoliciesEvaluated per request, before controller
Intercept and modify request/response flowmiddlewaresAttached in register() or referenced in route config
Access plugin features at runtimeGettersAny lifecycle or request handler

The following cards link directly to each dedicated page:

Backend customization

Plugin routes, controllers, services, policies, and middlewares follow the same conventions as backend customization in a standard Strapi application. The Server API wraps these into the plugin namespace automatically (see server content types for details on UIDs and naming conventions).

Registering a custom AI metadata provider​

GrowthThis feature is available with a Growth plan.

Plugins can register a custom provider through the Upload plugin's aiMetadataProvider service (see AI metadata generation).

A custom provider replaces Strapi AI as the source of the generated caption and alternative text.

Registering a custom provider requires the cms-byok-ai feature of an Enterprise license.

Without it, registerProvider() is silently ignored and the Media Library keeps using Strapi AI, if enabled.

Register the provider from the plugin's register() lifecycle phase.

Doing so keeps it in place before the Upload plugin's bootstrap() runs and considers registering the Strapi-managed provider:

src/plugins/my-plugin/strapi-server.js
module.exports = {
register({ strapi }) {
strapi.plugin('upload').service('aiMetadataProvider').registerProvider({
provider: {
name: 'my-custom-provider',
async generateMetadata({ images }) {
// `images` holds one Blob per file to describe.
// Return exactly one result per image, in the same order.
return {
results: images.map(() => ({
altText: 'Generated alt text',
caption: 'Generated caption',
})),
};
},
},
});
},
};

generateMetadata() must resolve with exactly one result per image, each with a non-empty altText and caption.

Caution

Only one AI metadata provider can be registered at a time. Registering a second one throws, naming the provider already in place.

A license with both cms-ai and cms-byok-ai is unsupported: which provider wins is undefined, since it depends on the plugins' bootstrap order.

Was this page helpful?