OpenAPI specification generation
Strapi provides a command-line tool to generate OpenAPI specifications for your applications.
The CLI tool automatically creates comprehensive API documentation that describes all available endpoints, parameters, and response formats in your Strapi application's Content API. Among the possible use cases, the generated specification can then be integrated into documentation tools like Swagger UI .
The OpenAPI generation feature is currently experimental. Its behavior and output might change in future releases without following semantic versioning. For additional information and context, please refer to the Strapi Contributor Docs .
Generating an OpenAPI specificationβ
The OpenAPI generation tool is included with Strapi core and doesn't require additional installation. You can use it directly from the command line in any Strapi project to generate comprehensive API documentation.
required metadataThe Admin panel can mark inner fields on a component as required, yet the generated OpenAPI file may still skip a required entry for those scalars. The parent object (for instance a component inside a dynamic zone) might list required while the nested properties do not. There is more background in GitHub issue #2236. Client generators that trust the raw schema alone can therefore emit types that look looser than what Strapi actually enforces.
This area is still experimental, same as the warning banner at the top of the page, so keep validating nested payloads in application code or with the REST validation helpers from the controllers guide instead of assuming every Admin rule is mirrored in the exported JSON schema yet.
CLI usageβ
Executing the command without any arguments will generate a specification.json file at the root of your Strapi folder project:
- Yarn
- NPM
yarn strapi openapi generate
npm run strapi openapi generate
You can also pass an optional --output argument to specify the path and filename, as in the following example:
- Yarn
- NPM
yarn strapi openapi generate --output ./docs/api-spec.json
npm run strapi openapi generate -- --output ./docs/api-spec.json
Specification structure and contentβ
The generated OpenAPI specification follows the OpenAPI 3.1.0 standard and could look like in the following shortened example:
The generated OpenAPI specification includes all available API endpoints in your Strapi application, and information about these endpoints, such as the following:
- CRUD operations for all content types
- Custom API routes defined in your application
- Authentication endpoints for user management
- File upload endpoints for media handling
- Plugin endpoints from installed plugins
Serving the specification over HTTPβ
Strapi can serve the generated OpenAPI specification as a live HTTP endpoint. Serving specifications over HTTP removes the need to regenerate a static file after each content-type change. Both the Content API and Admin API specifications can be served independently.
Both endpoints use access: 'disabled' by default and are not registered. Set access on 1 or both endpoints in the server configuration file to expose them.
Configurationβ
Add an openapi key to the server configuration:
- JavaScript
- TypeScript
module.exports = ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337),
openapi: {
'content-api': {
access: 'public',
route: {
path: '/openapi.json',
},
cache: {
enabled: true,
maxAgeMs: 60000,
filePath: '.strapi/openapi/content-api.json',
},
},
admin: {
access: 'authenticated',
route: {
path: '/openapi.json',
},
cache: {
enabled: true,
maxAgeMs: 60000,
filePath: '.strapi/openapi/admin.json',
},
},
},
});
export default ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337),
openapi: {
'content-api': {
access: 'public',
route: {
path: '/openapi.json',
},
cache: {
enabled: true,
maxAgeMs: 60000,
filePath: '.strapi/openapi/content-api.json',
},
},
admin: {
access: 'authenticated',
route: {
path: '/openapi.json',
},
cache: {
enabled: true,
maxAgeMs: 60000,
filePath: '.strapi/openapi/admin.json',
},
},
},
});
The content-api endpoint is served under the REST API prefix (/api by default). The full URL is http://localhost:1337/api/openapi.json. The admin endpoint is served under the admin path (/admin by default). The full URL is http://localhost:1337/admin/openapi.json.
Both endpoints must resolve to different full paths. If the content-api and admin endpoints resolve to the same URL, Strapi throws an error at startup.
Available optionsβ
Each endpoint (content-api and admin) accepts the following options:
| Option | Type | Default | Description |
|---|---|---|---|
access | String | 'disabled' | Controls whether the endpoint is registered and how it is protected. See Access control for accepted values per endpoint. |
route.path | String | '/openapi.json' | Path where the specification is served. Appended to the endpoint prefix (/api for content-api, /admin for admin). |
cache.enabled | Boolean | true | Enables file-based caching of the generated specification. |
cache.maxAgeMs | Number | 60000 | Maximum age of the cache file in milliseconds before regeneration. |
cache.filePath | String | '.strapi/openapi/<type>.json' | File path for the cache file. Relative paths are resolved from the application root. |
Access controlβ
The access option controls whether each endpoint is registered and how it is protected. Each endpoint supports different values:
Content API (content-api):
| Value | Behavior |
|---|---|
'disabled' (default) | The endpoint is not registered. |
'public' | The endpoint is registered without authentication. Anyone can fetch the specification. |
Admin (admin):
| Value | Behavior |
|---|---|
'disabled' (default) | The endpoint is not registered. |
'authenticated' | The endpoint requires an authenticated admin session. Any authenticated admin user can access the specification. |
Role-based access control for OpenAPI endpoints is not supported yet. The admin endpoint uses the admin::isAuthenticatedAdmin policy and does not filter by admin role or permission.
The Content API endpoint is always public when access is 'public'. If you do not want to expose the specification without authentication, leave content-api.access at 'disabled' and use the CLI to generate a static file instead.
Integrating with Swagger UIβ
If you registered an HTTP endpoint, you can point Swagger UI directly at the live URL (e.g., http://localhost:1337/api/openapi.json) instead of generating a static file. Skip step 1 below and use the endpoint URL as the url value in step 3.
With the following steps you can quickly generate a Swagger UI-compatible page:
-
Generate a specification:
- Yarn
- NPM
yarn strapi openapi generate --output ./public/swagger-spec.jsonnpm run strapi openapi generate -- --output ./public/swagger-spec.json -
Update the
/config/middlewares.jsconfiguration file with the following code:- JavaScript
- TypeScript
/config/middlewares.jsmodule.exports = [
'strapi::logger',
'strapi::errors',
{
name: 'strapi::security',
config: {
contentSecurityPolicy: {
useDefaults: true,
directives: {
'script-src': ["'self'", "'unsafe-inline'", 'https://unpkg.com'],
'style-src': ["'self'", "'unsafe-inline'", 'https://unpkg.com'],
'connect-src': ["'self'", 'https:'],
'img-src': ["'self'", 'data:', 'blob:', 'https:'],
'media-src': ["'self'", 'data:', 'blob:'],
upgradeInsecureRequests: null,
},
},
},
},
'strapi::cors',
'strapi::poweredBy',
'strapi::query',
'strapi::body',
'strapi::session',
'strapi::favicon',
'strapi::public',
];/config/middlewares.tsexport default [
'strapi::logger',
'strapi::errors',
{
name: 'strapi::security',
config: {
contentSecurityPolicy: {
useDefaults: true,
directives: {
'script-src': ["'self'", "'unsafe-inline'", 'https://unpkg.com'],
'style-src': ["'self'", "'unsafe-inline'", 'https://unpkg.com'],
'connect-src': ["'self'", 'https:'],
'img-src': ["'self'", 'data:', 'blob:', 'https:'],
'media-src': ["'self'", 'data:', 'blob:'],
upgradeInsecureRequests: null,
},
},
},
},
'strapi::cors',
'strapi::poweredBy',
'strapi::query',
'strapi::body',
'strapi::session',
'strapi::favicon',
'strapi::public',
];This will ensure the Swagger UI display from unpkg.com is not blocked by Strapi's CSP policy handled by the security middleware.
-
Create a
public/openapi.htmlfile in your Strapi project to display the Swagger UI, with the following code:<!DOCTYPE html>
<html>
<head>
<title>API Documentation</title>
<link
rel="stylesheet"
type="text/css"
href="https://unpkg.com/swagger-ui-dist@5.0.0/swagger-ui.css"
/>
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@5.0.0/swagger-ui-bundle.js"></script>
<script src="https://unpkg.com/swagger-ui-dist@5.0.0/swagger-ui-standalone-preset.js"></script>
<script>
window.onload = function () {
SwaggerUIBundle({
url: './swagger-spec.json',
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
layout: 'StandaloneLayout',
});
};
</script>
</body>
</html> -
Restart the Strapi server with
yarn developornpm run developand visit the/openapi.htmlpage. The Swagger UI should be displayed: