API Routes
In this chapter, you'll learn what API routes are and how to create them.
What is an API Route?#
An API route is a REST endpoint that exposes commerce features to external applications, such as storefronts, the Medusa Admin, or third-party systems.
The MedusaGo application provides a set of admin and store API routes out-of-the-box. They are the same routes that Medusa provides, with the same requests and responses. You can also create custom API routes to expose your custom functionalities.
How to Create an API Route?#
An API route is a Go value of type RouteFile from the framework/src/http package. It has two properties:
Path: The path of the API route. A path segment that starts with a colon, such as:id, is a path parameter.Route: The handler function of each HTTP method the route supports, such asGETandPOST.
An API route handler is a function that receives a MedusaRequest and a MedusaResponse, and returns an error. If it returns an error, the application's error handler sends the error response.
For example, to create a GET API route at /hello-world, add the following handler to a Go file under src/api of your project:
// helloGET handles GET /hello-world.
func helloGET(req *medusahttp.MedusaRequest, res *medusahttp.MedusaResponse) error {
return res.JSON(map[string]any{
"message": "[GET] Hello world!",
})
}
// helloPOST handles POST /hello-world.
func helloPOST(req *medusahttp.MedusaRequest, res *medusahttp.MedusaResponse) error {
return res.JSON(map[string]any{
"message": "[POST] Hello world!",
})
}
Then, define the RouteFile:
// HelloWorldRoute adds two API routes: GET /hello-world and POST /hello-world.
var HelloWorldRoute = medusahttp.RouteFile{
Path: "/hello-world",
Route: medusahttp.Route{
GET: helloGET,
POST: helloPOST,
},
}
GET and a POST handler. The HTTP Methods chapter explains the available HTTP methods.Register the API Route#
MedusaGo doesn't scan the file system for API routes. You register the routes of your project by passing them in the Routes option of the CLI, in the main.go file of your application.
For example:
// Options are the options main.go passes to the CLI.
func Options() cli.Options {
return cli.Options{
Config: medusaConfig,
Routes: Routes,
Middlewares: Middlewares,
}
}
Where Routes is a slice with every RouteFile of your project, and Middlewares is a slice with every middleware configuration. In this guide, they're defined in the src/api package, which you import in main.go:
// Routes lists every route file of the project.
var Routes = concat(
[]medusahttp.RouteFile{HelloWorldRoute, SumRoute, CreatePostRoute, WebhookRoute, StoreCustomRoute},
ParameterRoutes,
ResponseRoutes,
ErrorRoutes,
ProtectedRoutes,
)
// Middlewares lists every middleware configuration of the project.
var Middlewares = concat(
MiddlewaresExample,
SumMiddlewares,
CreatePostMiddlewares,
WebhookMiddlewares,
ProtectedMiddlewares,
StoreCustomMiddlewares,
[]medusahttp.MiddlewareRoute{CorsMiddleware},
)
// concat joins slices.
func concat[T any](lists ...[]T) []T {
var out []T
for _, l := range lists {
out = append(out, l...)
}
return out
}
src/api directory and the file names are conventions that follow the structure of a MedusaGo project. The only requirement is that every route file you want the application to serve is passed in cli.Options.Routes.The routes of your project are loaded after Medusa's API routes and the API routes of your plugins.
Test the API Route#
To test the API route above, start the MedusaGo application from the directory of your project:
Then, send a GET request to the /hello-world API route:
You should receive the following response:
The Request and Response Objects#
An API route handler receives a *MedusaRequest and a *MedusaResponse. MedusaRequest embeds Go's *http.Request, so you can use its methods and fields as usual, such as req.Method, req.Header, and req.URL.
These are the most used properties of MedusaRequest:
Property | Description |
|---|---|
| The path parameters, as a |
| The query parameters. |
| The parsed request body, and the bytes of the body if you configure the middleware to preserve them. |
| The body and query parameters, after the validation middlewares ran. |
| The Medusa container. Use its |
| The details of the authenticated actor, if any. Learn more in the Protected API Routes chapter. |
| The request's session. |
| The fields, pagination and filters that the |
| A |
MedusaRequest also has a Ctx() method. It returns the request's context, but it isn't canceled when the client disconnects. Pass it to the queries, workflows, and module services you run in the handler, so that the work isn't stopped halfway if the client closes the connection. Use req.Request.Context() if you need to detect that the client disconnected, such as in a stream.
The Response chapter explains the methods of MedusaResponse.
Routes Without a Prefix and Medusa's Prefixes#
The path prefix of an API route determines what MedusaGo applies to it automatically:
Prefix | Behavior |
|---|---|
| Requires an authenticated admin user, and applies the |
| Requires a publishable API key in the |
| Applies the |
Any other prefix | The route is public, and CORS isn't applied. For example, the |
Next Chapters: Learn More About API Routes#
Follow the next chapters to learn about the different HTTP methods you can use in API routes, parameters and validation, protecting routes, and more.