content/guides/09.extensions/2.api-extensions/2.endpoints.md
Endpoints allow you to register new API routes in your Directus project.
:partial{content="extensions-api"}
The index.js or index.ts file exports a register function that is read by Directus. It contains one or more route handlers, each being a sub-route of /<extension-name>.
export default (router, context) => {
router.get('/', (req, res) => res.send('Hello, World!'));
};
Alternatively, you can export a configuration object to be able to customize the root route:
export default {
id: 'greet',
handler: (router, context) => {
router.get('/', (req, res) => res.send('Hello, World!'));
router.get('/intro', (req, res) => res.send('Nice to meet you.'));
router.get('/goodbye', (req, res) => res.send('Goodbye!'));
},
};
The routes of this endpoint are accessible at /greet, /greet/intro and /greet/goodbye.
The register function receives the two parameters router and context. router is an Express router instance. context is an object with the following properties:
| Property | Description |
|---|---|
services | All API internal services. |
database | Knex instance that is connected to the current database. |
getSchema | Async function that reads the full available schema for use in services. |
env | Parsed environment variables. |
logger | Pino instance. |
emitter | Event emitter instance that can be used to emit custom events for other extensions. |
When using the sandbox, the register function receives the router object only. Each handler function receives only a request object and must return a response object.
interface SandboxEndpointRequest {
url: string;
headers: Record<string, string>;
body: any;
}
interface SandboxEndpointResponse {
status: number;
body: string | Record<string, unknown>;
}
You can import the SandboxEndpointRouter type from directus:api to type the router object:
/// <reference types="@directus/extensions/api.d.ts" />
import type { SandboxEndpointRouter } from 'directus:api';
export default (router: SandboxEndpointRouter) => {
router.get('/', () => {
return {
status: 200,
body: 'Hello World'
}
});
};
::callout{icon="material-symbols:menu-book-outline" color="primary" to="/guides/extensions/api-extensions/sandbox"} Learn more about the Directus sandbox for API extensions. ::
:partial{content="extensions-api-internals"}
In a route, call next(error) to hand off errors to our error-handler middleware. This prevent the request from hanging and ensures a consistent error response is returned instead of crashing the server.
router.get('/my-endpoint', async (req, res, next) => {
if (checkForError) {
next(new ForbiddenError());
return;
}
// continue with request processing...
});