Request validation helps you catch integration issues early by ensuring requests match expected schemas. Apicentric validates request bodies, query parameters, headers, and path parameters.
Why validate requests
Catch errors early : Identify invalid requests before they reach your application
Document expectations : Schemas serve as live documentation
Contract testing : Ensure clients send properly formatted data
Debugging : Get clear error messages when requests don’t match
Basic request body validation
Define the expected structure for request bodies:
endpoints :
- method : POST
path : /users
request_body :
content_type : application/json
schema : |
{
"username": "string",
"email": "string",
"age": "number"
}
responses :
201 :
content_type : application/json
body : |
{
"id": {{faker "datatype.number"}},
"username": "{{request.body.username}}",
"email": "{{request.body.email}}",
"age": {{request.body.age}}
}
400 :
content_type : application/json
body : |
{
"error": "Validation failed",
"message": "Request body does not match expected schema"
}
curl -X POST http://localhost:9000/api/users \
-H "Content-Type: application/json" \
-d '{
"username": "alice",
"email": "[email protected] ",
"age": 25
}'
curl -X POST http://localhost:9000/api/users \
-H "Content-Type: application/json" \
-d '{
"username": "alice",
"age": "not-a-number"
}'
You’ll receive a 400 error with validation details.
Validating query parameters
Define expected query parameters:
endpoints :
- method : GET
path : /products
description : List products with filtering
parameters :
- name : category
in : query
required : false
type : string
description : Filter by product category
- name : limit
in : query
required : false
type : integer
description : Maximum number of results
- name : min_price
in : query
required : false
type : number
description : Minimum price filter
responses :
200 :
content_type : application/json
body : |
{
"category": "{{query.category}}",
"limit": "{{query.limit}}",
"min_price": "{{query.min_price}}",
"products": []
}
Test it:
curl "http://localhost:9000/api/products?category=electronics&limit=10&min_price=99.99"
Required vs optional fields
Control which fields are mandatory:
endpoints :
- method : POST
path : /orders
request_body :
content_type : application/json
schema : |
{
"customer_id": "number",
"items": [{"product_id": "number", "quantity": "number"}],
"notes": "string?"
}
responses :
201 :
content_type : application/json
body : |
{
"order_id": {{faker "datatype.number" min=1000 max=9999}},
"customer_id": {{request.body.customer_id}},
"items": {{json request.body.items}},
"status": "pending"
}
422 :
condition : "{{not request.body.customer_id}}"
content_type : application/json
body : |
{
"error": "Validation failed",
"details": ["customer_id is required"]
}
Use the ? suffix to mark fields as optional: "field": "string?". All fields without ? are required by default.
Ensure required headers are present:
endpoints :
- method : GET
path : /profile
description : Get user profile (requires authentication)
header_match :
Authorization : "Bearer *"
X-API-Version : "v1"
responses :
200 :
content_type : application/json
body : |
{
"id": 1,
"name": "User",
"email": "[email protected] "
}
401 :
content_type : application/json
body : |
{
"error": "Unauthorized",
"message": "Missing or invalid Authorization header"
}
Test with headers:
curl http://localhost:9000/api/profile \
-H "Authorization: Bearer abc123" \
-H "X-API-Version: v1"
Complex nested schemas
Validate deeply nested objects:
endpoints :
- method : POST
path : /checkout
request_body :
content_type : application/json
schema : |
{
"customer": {
"id": "number",
"email": "string"
},
"items": [
{
"product_id": "number",
"quantity": "number",
"price": "number"
}
],
"shipping": {
"address": "string",
"city": "string",
"zip": "string",
"country": "string"
},
"payment": {
"method": "string",
"card_last4": "string?"
}
}
responses :
201 :
content_type : application/json
body : |
{
"checkout_id": {{faker "datatype.uuid"}},
"total": {{faker "commerce.price"}},
"status": "pending"
}
Validation error responses
Provide helpful error messages when validation fails:
endpoints :
- method : POST
path : /api/register
request_body :
content_type : application/json
schema : |
{
"email": "string",
"password": "string",
"age": "number"
}
responses :
201 :
condition : "{{and request.body.email request.body.password}}"
content_type : application/json
body : |
{
"id": {{faker "datatype.number"}},
"email": "{{request.body.email}}"
}
400 :
condition : "{{not request.body.email}}"
content_type : application/json
body : |
{
"error": "Validation failed",
"field": "email",
"message": "Email is required"
}
422 :
condition : "{{lt request.body.age 18}}"
content_type : application/json
body : |
{
"error": "Validation failed",
"field": "age",
"message": "Must be 18 or older"
}
Validating content types
Ensure the correct Content-Type header:
endpoints :
- method : POST
path : /upload
request_body :
content_type : multipart/form-data
responses :
200 :
content_type : application/json
body : |
{
"uploaded": true,
"filename": "{{request.body.filename}}"
}
415 :
content_type : application/json
body : |
{
"error": "Unsupported Media Type",
"message": "Expected multipart/form-data"
}
Using validation helpers
Apicentric provides template helpers for common validations:
Email validation
Length validation
Range validation
Type validation
responses :
400 :
condition : "{{not (contains request.body.email '@')}}"
content_type : application/json
body : |
{
"error": "Invalid email format"
}
Testing validation
Create a comprehensive test suite:
# Valid request
curl -X POST http://localhost:9000/api/users \
-H "Content-Type: application/json" \
-d '{"username": "alice", "email": "[email protected] ", "age": 25}'
# Missing required field
curl -X POST http://localhost:9000/api/users \
-H "Content-Type: application/json" \
-d '{"username": "alice", "age": 25}'
# Wrong type
curl -X POST http://localhost:9000/api/users \
-H "Content-Type: application/json" \
-d '{"username": "alice", "email": "[email protected] ", "age": "not-a-number"}'
# Invalid email format
curl -X POST http://localhost:9000/api/users \
-H "Content-Type: application/json" \
-d '{"username": "alice", "email": "invalid-email", "age": 25}'
Debugging validation failures
Enable verbose logging to see validation details:
apicentric simulator start --services-dir . --verbose
You’ll see detailed logs for each request:
📥 Request: POST /api/users
📋 Headers: {"Content-Type": "application/json"}
📦 Body: {"username": "alice", "age": 25}
❌ Validation failed: Missing required field 'email'
📤 Response: 400 Bad Request
Validation errors return 400 Bad Request by default. Customize error responses using the condition field to return different status codes like 422 Unprocessable Entity.
Best practices
Start simple : Begin with basic type validation, then add complexity
Clear error messages : Help developers understand what went wrong
Document schemas : Use the description field to explain requirements
Test edge cases : Validate boundary conditions and invalid inputs
Use realistic data : Test with data that matches production scenarios
Next steps
Contract testing Validate your mocks against real APIs
Import specs Import existing OpenAPI specs with validation
Export specs Generate OpenAPI specs from your services
Creating mocks Learn more about mock API features