REST API Guide
REST API Guide
Section titled “REST API Guide”Overview
Section titled “Overview”The API Gateway automatically generates RESTful HTTP endpoints from your service contracts. Services never handle HTTP - they define contracts, and REST endpoints are created automatically.
Auto-Generated Endpoints
Section titled “Auto-Generated Endpoints”URL Pattern
Section titled “URL Pattern”The API Gateway generates RESTful URLs following standard conventions:
POST /api/users → CreateUserCommandGET /api/users/:id → GetUserQueryPUT /api/users/:id → UpdateUserCommandDELETE /api/users/:id → DeleteUserCommandGET /api/users → ListUsersQueryKey Pattern: Resource names are derived from contract message types:
CreateUserCommand→/api/usersGetOrderQuery→/api/orders/:idListProductsQuery→/api/products
HTTP Method Mapping
Section titled “HTTP Method Mapping”| Contract Type | HTTP Method | Example |
|---|---|---|
| Create*Command | POST | POST /api/users |
| Update*Command | PUT | PUT /api/users/:id |
| Delete*Command | DELETE | DELETE /api/users/:id |
| Get*Query | GET | GET /api/users/:id |
| List*Query | GET | GET /api/users |
| *Command | POST | POST /api/actions |
| *Query | GET | GET /api/data |
Creating REST Endpoints
Section titled “Creating REST Endpoints”1. Define a Contract
Section titled “1. Define a Contract”Create a contract in your service:
import { createContract } from '@banyanai/platform-contract-system';
export const CreateUserContract = createContract({ messageType: 'CreateUserCommand', targetService: 'user-service', inputSchema: { type: 'object', properties: { email: { type: 'string', format: 'email' }, name: { type: 'string' }, role: { type: 'string', enum: ['user', 'admin'] } }, required: ['email', 'name'] }, outputSchema: { type: 'object', properties: { id: { type: 'string' }, email: { type: 'string' }, name: { type: 'string' }, role: { type: 'string' }, createdAt: { type: 'string', format: 'date-time' } }, required: ['id', 'email', 'name', 'role', 'createdAt'] }, requiredPermissions: ['users:create']});2. Implement the Handler
Section titled “2. Implement the Handler”Write only business logic:
import { CommandHandler } from '@banyanai/platform-cqrs';import { CreateUserContract } from '../contracts/CreateUserContract.js';
@CommandHandler(CreateUserContract)export class CreateUserHandler { async handle(input: { email: string; name: string; role?: string }) { // Pure business logic - no HTTP code const user = await this.userRepository.create({ email: input.email, name: input.name, role: input.role || 'user' });
return { id: user.id, email: user.email, name: user.name, role: user.role, createdAt: user.createdAt }; }}3. Endpoint Generated Automatically
Section titled “3. Endpoint Generated Automatically”The API Gateway creates:
POST http://localhost:3003/api/usersMaking REST API Calls
Section titled “Making REST API Calls”POST Request (Commands)
Section titled “POST Request (Commands)”curl -X POST http://localhost:3003/api/users \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "email": "alice@example.com", "name": "Alice Smith", "role": "user" }'Response:
{ "id": "usr_1234567890", "email": "alice@example.com", "name": "Alice Smith", "role": "user", "createdAt": "2025-11-15T10:30:00Z"}GET Request (Queries)
Section titled “GET Request (Queries)”# Get single resourcecurl -X GET http://localhost:3003/api/users/usr_1234567890 \ -H "Authorization: Bearer YOUR_JWT_TOKEN"
# List resourcescurl -X GET http://localhost:3003/api/users?limit=10&offset=0 \ -H "Authorization: Bearer YOUR_JWT_TOKEN"PUT Request (Updates)
Section titled “PUT Request (Updates)”curl -X PUT http://localhost:3003/api/users/usr_1234567890 \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Alice Johnson", "role": "admin" }'DELETE Request
Section titled “DELETE Request”curl -X DELETE http://localhost:3003/api/users/usr_1234567890 \ -H "Authorization: Bearer YOUR_JWT_TOKEN"Path Parameters
Section titled “Path Parameters”For queries with IDs, the API Gateway automatically extracts path parameters:
// GetUserQuery contractexport const GetUserContract = createContract({ messageType: 'GetUserQuery', targetService: 'user-service', inputSchema: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] }, outputSchema: { /* user object */ }});Generated endpoint:
GET /api/users/:idThe id parameter is extracted and passed to the handler:
curl http://localhost:3003/api/users/usr_123# Handler receives: { id: "usr_123" }Query Parameters
Section titled “Query Parameters”For list endpoints, query parameters are passed to handlers:
GET /api/users?limit=10&offset=0&role=admin# Handler receives: { limit: 10, offset: 0, role: "admin" }Response Codes
Section titled “Response Codes”The API Gateway automatically maps responses to HTTP status codes:
| Scenario | Status Code | Description |
|---|---|---|
| Success (Command) | 201 Created | Resource created |
| Success (Query) | 200 OK | Data retrieved |
| Success (Update) | 200 OK | Resource updated |
| Success (Delete) | 204 No Content | Resource deleted |
| Validation Error | 400 Bad Request | Invalid input |
| Unauthorized | 401 Unauthorized | Missing/invalid auth |
| Forbidden | 403 Forbidden | Insufficient permissions |
| Not Found | 404 Not Found | Resource doesn’t exist |
| Server Error | 500 Internal Server Error | Handler exception |
Error Responses
Section titled “Error Responses”Errors are returned in a standard format:
{ "error": "ValidationError", "message": "Invalid email format", "correlationId": "cor_abc123xyz", "timestamp": "2025-11-15T10:30:00Z", "details": { "field": "email", "constraint": "format" }}CORS Configuration
Section titled “CORS Configuration”The API Gateway enables CORS by default:
// Configured in API Gateway{ origin: '*', methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization'], credentials: true}OpenAPI Documentation
Section titled “OpenAPI Documentation”The API Gateway generates OpenAPI/Swagger documentation automatically:
# Access Swagger UIhttp://localhost:3003/api-docs
# Download OpenAPI spechttp://localhost:3003/api-docs/openapi.jsonBest Practices
Section titled “Best Practices”1. Use Resource-Oriented Contracts
Section titled “1. Use Resource-Oriented Contracts”// Good: Resource-orientedCreateUserCommand → POST /api/usersGetUserQuery → GET /api/users/:id
// Avoid: Action-oriented (still works but less RESTful)RegisterUserCommand → POST /api/register-user2. Include Proper Validation
Section titled “2. Include Proper Validation”inputSchema: { type: 'object', properties: { email: { type: 'string', format: 'email', maxLength: 255 }, age: { type: 'number', minimum: 0, maximum: 150 } }, required: ['email']}3. Set Appropriate Permissions
Section titled “3. Set Appropriate Permissions”export const CreateUserContract = createContract({ messageType: 'CreateUserCommand', targetService: 'user-service', requiredPermissions: ['users:create'], // ← Enforce permissions // ...});4. Document Your Schemas
Section titled “4. Document Your Schemas”inputSchema: { type: 'object', properties: { email: { type: 'string', format: 'email', description: 'User email address for authentication' }, name: { type: 'string', description: 'Full name of the user' } }}Troubleshooting
Section titled “Troubleshooting”Endpoint Not Found (404)
Section titled “Endpoint Not Found (404)”Cause: Service not registered or contract not discovered
Solution: Check contract cache:
curl http://localhost:3003/debug/contractsVerify your service is running and contracts are broadcast.
Unauthorized (401)
Section titled “Unauthorized (401)”Cause: Missing or invalid JWT token
Solution: Include valid Bearer token:
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \ http://localhost:3003/api/usersForbidden (403)
Section titled “Forbidden (403)”Cause: User lacks required permissions
Solution: Verify user has permissions in contract’s requiredPermissions:
requiredPermissions: ['users:create']Next Steps
Section titled “Next Steps”- GraphQL API Guide - Alternative to REST
- API Contracts - Contract best practices
- API Security - Authentication and authorization