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
is a special file that contains the router handlersCopy to clipboardroute.{ts|js}
- HTTP methods are defined by the route handler name; hereCopy to clipboard
GET
In the example above, we register a
route at pathCopy to clipboardGET
.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
route at pathCopy to clipboardPOST
. The brackets in the file path,Copy to clipboard/admin/products/:id
, specify a parameter that can be accessed within the handler.Copy to clipboardapi/admin/products/[id]/route.ts
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
. In this file, you can register middleware to all endpoints, a subset of endpoints, or one at a time.Copy to clipboardapi/middlewares.{ts|js}
1234567891011// api/middlewares.tsexport const config: MiddlewaresConfig = {routes: [{method: ["GET", "POST"],matcher: "/store/*",middlewares: [someStoreMiddleware],},],}
Per default, middleware is registered globally. The
option is required to configure the paths the middlewares apply to. TheCopy to clipboardmatcher
option is used to configure the specific methods the middlewares apply to.Copy to clipboardmethod
In the example above, we register a middleware,
, to all paths starting withCopy to clipboardsomeStoreMiddleware
that use HTTP methodsCopy to clipboard/store
andCopy to clipboardGET
.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
andCopy to clipboardMedusaRequest
to offer an even better experience with access to types specific to our Request and Response context, such as the Awilix dependency container living atCopy to clipboardMedusaResponse
.Copy to clipboardreq.scope
Share this post