Today, we are excited to announce API Routes – a massive improvement of the developer experience of a core concept in Medusa’s extensibility toolbox.
We are highly committed to delivering a world-class experience across all our products. With our commerce primitives and tooling, developers can effortlessly build unique digital commerce applications at record speed.
API Routes
API Routes in Medusa is a place for developers to add custom logic that HTTP requests can trigger. The endpoints have direct access to Medusa’s core services like the Product and Cart services and custom services added to your project or in installed plugins.
To create a custom endpoint in Medusa, developers have had to familiarize themselves with application routing and Express more generally. This created friction unrelated to our product, leading to frustration from users, the community, and our support team.
Today, we are introducing API Routes - drastically simplifying creating custom endpoints in Medusa.
Developers can now create custom routes using simple JavaScript without worrying about the intricacies of the Express Router. Routes are registered using the file system, an approach familiar to many from frameworks like Next.js and Svelte.
12345678910// api/admin/products/route.tsimport { MedusaRequest, MedusaResponse } from "@medusajs/medusa"export async function GET(req: MedusaRequest, res: MedusaResponse) {const productService = req.scope.resolve("productService")const products = await productService.list()res.json({ products })}
The example above illustrates a few key points of API Routes:
- Endpoint paths are inferred from the file path
- Copy to clipboard
route.{ts|js}
is a special file that contains the router handlers - HTTP methods are defined by the route handler name; here Copy to clipboard
GET
In the example above, we register a Copy to clipboardGET
route at path Copy to clipboard/admin/products
.
Dynamic Segments
API Routes support dynamic URL segments and are similarly registered through the file system.
1234567891011121314// api/admin/products/[id]/route.tsimport { MedusaRequest, MedusaResponse } from "@medusajs/medusa"export async function POST(req: MedusaRequest, res: MedusaResponse) {const { id } = req.paramsconst { payload } = req.bodyconst productService = req.scope.resolve("productService")const product = await productService.update(id, payload)res.json({ product })}
In the example above, we register a Copy to clipboardPOST
route at path Copy to clipboard/admin/products/:id
. The brackets in the file path, Copy to clipboardapi/admin/products/[id]/route.ts
, specify a parameter that can be accessed within the handler.
You can add as many dynamic segments as you’d like. However, if the parameter names clash, an error will be thrown, and your application will terminate.
Middlewares
Adding middleware to routes has also been simplified. With API Routes, we are centralizing all middlewares in a file at Copy to clipboardapi/middlewares.{ts|js}
. In this file, you can register middleware to all endpoints, a subset of endpoints, or one at a time.
1234567891011// api/middlewares.tsexport const config: MiddlewaresConfig = {routes: [{method: ["GET", "POST"],matcher: "/store/*",middlewares: [someStoreMiddleware],},],}
Per default, middleware is registered globally. The Copy to clipboardmatcher
option is required to configure the paths the middlewares apply to. The Copy to clipboardmethod
option is used to configure the specific methods the middlewares apply to.
In the example above, we register a middleware, Copy to clipboardsomeStoreMiddleware
, to all paths starting with Copy to clipboard/store
that use HTTP methods Copy to clipboardGET
and Copy to clipboardPOST
.
What’s next?
We are excited to hear your thoughts about our new API Routes. If you have any feedback or experience issues, don’t hesitate to post on our GitHub Issues board or GitHub Discussions.
In the future, we plan to extend the Copy to clipboardMedusaRequest
and Copy to clipboardMedusaResponse
to offer an even better experience with access to types specific to our Request and Response context, such as the Awilix dependency container living at Copy to clipboardreq.scope
.