Appearance
API Architecture & Conventions
The MEGSTAT POS HTTP API is built on Hono, served over HTTP/1.1 and HTTP/2, mounted under the /api prefix, and uses standard JSON payloads.
Authentication
Every API call (except /health and initial login) requires a verified JSON Web Token (JWT) passed in the Authorization header:
http
Authorization: Bearer <jwt_access_token>Tokens are obtained via POST /api/auth/login or POST /api/auth/pin.
- Default token TTL: 8 hours (
JWT_TTL_SECONDS=28800). - Tokens encode the authenticated
userId, activetenantId, and assignedroles.
Response Envelopes
To ensure frontend type safety and predictable deserialization, all responses adhere to unified response envelopes.
Success Envelope
Built by helper functions in backend/src/http/response.ts (ok, created, accepted, withData):
json
{
"success": true,
"data": { ... }
}Paginated Success Envelope
Built by paginated(c, items, pagination, meta):
json
{
"success": true,
"data": [ ... ],
"pagination": {
"page": 1,
"limit": 25,
"total": 142,
"totalPages": 6
},
"meta": {
"summaryCount": 142
}
}Error Envelope
Built by the global error handler backend/src/http/error.ts:
json
{
"success": false,
"error": {
"code": "INSUFFICIENT_STOCK",
"message": "Product SKU-104 has insufficient inventory to fulfill sale",
"details": [
{
"field": "items[0].qty",
"message": "Available: 2, Requested: 5"
}
]
},
"requestId": "req_c7a19f40"
}Standard Error Codes
| HTTP Status | Error Code | Description |
|---|---|---|
400 | VALIDATION_ERROR | Request payload failed Zod schema validation |
401 | UNAUTHORIZED | Missing, expired, or malformed JWT token |
403 | FORBIDDEN | Caller lacks required RBAC permission |
404 | NOT_FOUND | Target entity does not exist within the tenant |
409 | CONFLICT | Unique constraint violation or concurrency collision |
422 | BUSINESS_RULE_VIOLATION | Logical constraint failed (e.g. closed shift, exceeded credit limit) |
429 | RATE_LIMITED | Rate limit threshold exceeded |
500 | INTERNAL_SERVER_ERROR | Unhandled server exception |
Input Validation & Coercion
All mutation endpoints strictly validate incoming request bodies against @megstat/schemas:
- Schemas apply type coercions where appropriate (e.g.
z.coerce.number()for stringified decimal inputs). - Whitespace is automatically trimmed via
.trim(). - Missing optional fields receive schema-defined defaults.
