MuleSoft APIkit Router
The APIkit Router is MuleSoft's component for building APIs from a RAML or OAS specification. Instead of manually creating one flow per endpoint, APIkit reads your API specification and generates the routing logic automatically. Each endpoint in your RAML spec becomes a separate flow, and APIkit routes incoming requests to the correct flow based on the HTTP method and path.
How APIkit Works
The APIkit Router sits at the front of your application. Every incoming request first hits the APIkit Router. The router reads the request path and method, consults the RAML specification, and directs the request to the matching implementation flow. If the request does not match any defined endpoint, APIkit automatically returns a 404 response. If the request body does not match the RAML data type, APIkit returns a 400 Bad Request.
APIkit Request Routing Diagram
Incoming Requests:
GET /products ─┐
POST /products ─┤
GET /products/P-001 ─┤─→ [HTTP Listener: /*]
DELETE /products/P-001─┘ │
▼
[APIkit Router]
(reads api.raml)
/ | | \
▼ ▼ ▼ ▼
[get: [post: [get: [delete:
/prod] /prod] /prod/ /prod/
{id}] {id}]
Generating an APIkit Project from RAML
The fastest way to use APIkit is to scaffold the entire project from an existing RAML file.
Steps in Anypoint Studio:
- Go to File > New > Mule Project
- Enter a project name like
products-api - Check the box Add APIkit components
- Select your RAML file or import it from Anypoint Exchange
- Click Finish
Studio reads the RAML and generates:
- A main flow with the HTTP Listener and APIkit Router
- One implementation flow per endpoint defined in the RAML
- An error handler flow for 400 and 404 responses
Generated Flow Structure
Generated Flows from a Products RAML Spec
products-api.xml
│
├── products-api-main ← Main flow (do not modify)
│ [HTTP Listener: 0.0.0.0:8081 /*]
│ [APIkit Router: config=products-api-config]
│
├── get:\products:products-api-config ← GET /products
│ [Logger: "Get all products"]
│ [Set Payload: ...] ← You implement this
│
├── post:\products:products-api-config ← POST /products
│ [Logger: "Create product"]
│ [Set Payload: ...] ← You implement this
│
├── get:\products\{id}:products-api-config ← GET /products/{id}
│ [Logger: "Get product by ID"]
│ [Set Payload: ...] ← You implement this
│
├── put:\products\{id}:products-api-config ← PUT /products/{id}
│
├── delete:\products\{id}:products-api-config ← DELETE /products/{id}
│
└── products-api-console ← API Console (optional, remove in prod)
Implementing an Endpoint Flow
After generation, each endpoint flow contains only placeholder components. You replace those placeholders with real logic — database queries, calls to other APIs, transformations, and so on.
Implementing GET /products
Flow: get:\products:products-api-config
BEFORE (generated placeholder):
[Set Payload: ""] ← empty, needs implementation
AFTER (your implementation):
[Database: SELECT id, name, category, price FROM products ORDER BY name]
│
▼
[Transform Message]
%dw 2.0
output application/json
---
payload map (row) -> {
"id": row.ID,
"name": row.NAME,
"category": row.CATEGORY,
"price": row.PRICE as Number
}
Accessing URI Parameters in APIkit Flows
For flows that handle paths with URI parameters like /products/{id}, access the captured value using attributes.uriParams.id.
Flow: get:\products\{id}:products-api-config
[Database: SELECT * FROM products WHERE id = '#[attributes.uriParams.id]']
│
▼
[Choice Router]
Is payload empty? (sizeOf(payload) == 0)
│
├── YES (not found):
│ [Set Payload: {"message": "Product not found"}]
│ [Set Variable: httpStatus = 404]
│
└── NO (found):
[Transform: row to JSON object]
[Set Variable: httpStatus = 200]
APIkit Validation
One of the biggest benefits of APIkit is automatic request validation. When a POST request arrives with a body that does not match the RAML data type definition, APIkit rejects it with a 400 Bad Request before the implementation flow even runs. You get free input validation by defining your types correctly in RAML.
Automatic Validation Diagram
RAML defines for POST /products:
Required fields: name (string), price (number)
Valid request body:
{ "name": "Pen", "price": 1.50 }
→ APIkit passes to implementation flow ✓
Invalid request body (missing price):
{ "name": "Pen" }
→ APIkit returns 400 Bad Request automatically ✗
→ Implementation flow never runs
Invalid request body (wrong type):
{ "name": "Pen", "price": "cheap" }
→ APIkit returns 400 Bad Request automatically ✗
APIkit Error Flows
APIkit generates two error-handling flows automatically:
- 400 flow: Returns a 400 Bad Request when the request body or parameters fail RAML validation.
- 404 flow: Returns a 404 Not Found when the request path does not match any defined endpoint.
You can customize these flows to return your organization's standard error response format.
Customizing the 404 Error Flow
Flow: get:\products\{id}:404
Default generated response:
{ "message": "Resource not found" }
Your custom response:
{
"errorCode": "PRODUCT_NOT_FOUND",
"message": "No product exists with ID: " ++ attributes.uriParams.id,
"timestamp": now() as String {format: "yyyy-MM-dd'T'HH:mm:ss"},
"requestId": vars.correlationId
}
Disabling the API Console in Production
APIkit generates an API Console flow that creates a browsable interface for your API at /console. This is useful in development for testing endpoints. Remove this flow or disable the route in production. Exposing an API console in production reveals your API structure to potential attackers.
Updating the APIkit Config When RAML Changes
When your RAML specification changes — a new endpoint is added, a parameter is renamed — regenerate the APIkit flows. Right-click on the APIkit Router in the canvas and select Regenerate Flows. Studio adds flows for new endpoints. Existing implementation flows are not overwritten, so your business logic stays intact.
