API Overview
The eTeamups Platform exposes a RESTful API through an Nginx reverse-proxy gateway. All service endpoints are reachable through a single base URL, with path prefixes routing requests to the appropriate microservice.
Base URL
| Environment | Base URL |
|---|---|
| Production | https://api.zeswa.com |
| Local development | https://localhost:18443 |
Every service is mounted at a top-level path prefix:
| Prefix | Service | Internal Port |
|---|---|---|
/auth |
Auth Service | 9000 |
/profile |
Profile Service | 9100 |
/organisation |
Organisation Service | 9107 |
/media |
Media Service | 9102 |
/evaluation |
Evaluation Service | 9103 |
Nginx strips the prefix before forwarding the request. For example, a request to https://api.zeswa.com/auth/login is forwarded to the Auth Service as POST /login.
Authentication
Most endpoints require a valid JSON Web Token (JWT) issued by the Auth Service. Include the token in the Authorization header:
Authorization: Bearer <accessToken>
Token lifecycle
- Login – Call
POST /auth/loginwithemailAddressandcodeChallengeto receive an initialaccessTokenandrefreshToken. - Verify – Call
POST /auth/verifywith the OTP sent to the user’s email and thecodeVerifier(PKCE). After successful verification the token is fully activated. - Refresh – Call
POST /auth/tokenwith a validrefreshTokento obtain a new token pair before the access token expires.
If the Authorization header is missing, the API returns 401 Unauthorized. If the token is present but invalid or expired, the API returns 403 Forbidden.
Common Response Format
Successful responses return a JSON body with the relevant resource data. List endpoints typically return an array, while single-resource endpoints return an object.
{
"statusCode": 200,
"data": { ... }
}
Error Handling
Errors are returned using the Boom error format, which provides a consistent structure across all services:
{
"statusCode": 400,
"error": "Bad Request",
"message": "Descriptive error message"
}
Standard HTTP status codes
| Code | Meaning |
|---|---|
200 |
Success |
201 |
Resource created |
400 |
Bad request – validation failed or missing required fields |
401 |
Unauthorized – missing Authorization header |
403 |
Forbidden – invalid or expired token |
404 |
Resource not found |
409 |
Conflict – duplicate resource |
429 |
Too Many Requests – rate limit exceeded |
500 |
Internal server error |
Request Validation
All request bodies are validated with Zod schemas on the server side. If validation fails, the response will be a 400 Bad Request with a message field describing which fields failed and why.
Example validation error:
{
"statusCode": 400,
"error": "Bad Request",
"message": "\"emailAddress\" must be a valid email"
}
Rate Limiting
Nginx enforces two rate-limiting zones:
| Zone | Rate | Applied to |
|---|---|---|
login |
5 requests per minute per IP | /auth endpoints |
api |
10 requests per second per IP | /profile, /organisation, /media endpoints |
Both zones allow a burst buffer (burst=10 for login, burst=20 for API) with nodelay, meaning burst requests are served immediately but the average rate is enforced over time. Exceeding the limit returns HTTP 429.
CORS Configuration
Cross-Origin Resource Sharing headers are managed at the application level by each microservice. Requests from allowed origins will receive appropriate Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers response headers.
Health Check Endpoints
Every service exposes two utility endpoints that do not require authentication:
| Endpoint | Description |
|---|---|
GET /health |
Returns a simple health status. Used by Docker health checks and monitoring. |
GET /_ping |
Lightweight liveness probe. |
Through the gateway these become /auth/health, /profile/health, /organisation/health, and /media/health.
OpenAPI Specification
A machine-readable OpenAPI 3.0.3 specification that covers all services is maintained in the repository:
- YAML:
swagger/zeswa-hub-open-api.yaml - JSON:
swagger/zeswa-hub-open-api.json
The specification is auto-generated from Express routers. Import either file into tools such as Swagger UI, Postman, or Insomnia for interactive testing.
Content Type
All API endpoints accept and return application/json unless otherwise noted. The Media Service additionally accepts multipart/form-data for file uploads and serves binary image data.
Request Size Limits
- Default body size limit: 50 MB (set in the Nginx
httpblock). - Media upload limit: 100 MB (set specifically for the
/medialocation block).