This document summarizes the implementation of standardized error and success envelopes across all API routes in the Fluxora Backend. The goal was to ensure consistent response structures for both successful and error responses, making the API more predictable and easier to consume.
Before:
export interface ErrorEnvelope {
success: false;
error: string;
code: string;
details?: string;
field?: string;
}
export function errorResponse(
error: string,
code: string,
details?: string,
field?: string
): ErrorEnvelopeAfter:
export interface ErrorDetail {
code: string;
message: string;
details?: unknown;
requestId?: string;
}
export interface ErrorEnvelope {
success: false;
error: ErrorDetail;
}
export function errorResponse(
code: string,
message: string,
details?: unknown,
requestId?: string
): ErrorEnvelopeKey Changes:
- Restructured error envelope to nest error details under
errorproperty - Changed parameter order to
code, message, details, requestIdfor consistency - Made
detailstype more flexible (unknowninstead ofstring) - Added
requestIdsupport for better debugging
Changes:
- Imported
errorResponsehelper fromutils/response.ts - Updated all error responses to use the standardized
errorResponse()function - Ensured consistent error envelope structure across all error types:
DecimalSerializationErrorApiErrorentity.too.largeerrors- Unexpected errors
Example:
// Before
res.status(400).json({
error: {
code: ApiErrorCode.DECIMAL_ERROR,
message: err.message,
details: { decimalErrorCode: err.code, field: err.field },
requestId,
},
});
// After
res.status(400).json(
errorResponse(
ApiErrorCode.DECIMAL_ERROR,
err.message,
{ decimalErrorCode: err.code, field: err.field },
requestId
)
);- Imported
successResponsehelper - Wrapped all successful responses in
successResponse():- Stream listing (GET /api/streams)
- Stream retrieval (GET /api/streams/:id)
- Stream creation (POST /api/streams)
- Stream cancellation (DELETE /api/streams/:id)
- Ensured
requestIdis passed to all response helpers
- Already using
successResponseanderrorResponse✓ - No changes needed
- Imported
successResponsehelper - Wrapped audit log response in
successResponse() - Added
requestIdsupport
- Imported
successResponseanderrorResponsehelpers - Updated all responses to use standardized envelopes:
- DLQ listing (GET /admin/dlq)
- DLQ entry retrieval (GET /admin/dlq/:id)
- DLQ entry deletion (DELETE /admin/dlq/:id)
- Operator role enforcement errors
- Replaced inline validation errors with
validationError()helper
- Imported
successResponsehelper - Wrapped indexer ingestion response in
successResponse()
- Imported
successResponseanderrorResponsehelpers - Updated all webhook endpoints:
- Delivery status (GET /api/webhooks/deliveries/:deliveryId)
- Delivery listing (GET /api/webhooks/deliveries)
- Signature verification (POST /api/webhooks/verify)
- Retry processing (POST /internal/webhooks/retry)
- Imported
successResponseanderrorResponsehelpers - Updated root endpoint (GET /) to use
successResponse() - Updated 404 handler to use
errorResponse()
- Added comprehensive tests for
successResponse()anderrorResponse()helpers - Tests cover:
- Success envelope structure
- Error envelope structure
- Optional fields (requestId, details)
- Different data types
- Envelope consistency
- Updated all test assertions to expect standardized envelope structure
- Changed from
res.body.fieldtores.body.data.fieldfor success responses - Changed from
res.body.errortores.body.error.messagefor error responses - Added
successfield assertions
- Updated test assertions to expect standardized envelope structure
- Changed from
res.body.fieldtores.body.data.field - Changed from
res.body.timestamptores.body.meta.timestamp
- Updated all HTTP status code examples to show standardized envelope structure
- Updated error response format section
- Changed error codes from
snake_casetoUPPER_SNAKE_CASE - Added success response structure documentation
- Updated all failure mode examples
- Added
SuccessResponseschema definition - Updated
ErrorResponseschema to match new structure - Removed
statusfield from error response (redundant with HTTP status code) - Changed error codes to
UPPER_SNAKE_CASE - Added
successfield to both schemas
{
"success": true,
"data": {
// Response payload
},
"meta": {
"timestamp": "2024-01-01T12:00:00.000Z",
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Human-readable error message",
"details": {
// Optional additional context
},
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}
}- Consistency: All API responses follow the same structure
- Type Safety: TypeScript interfaces ensure compile-time correctness
- Debugging:
requestIdin every response enables log correlation - Client-Friendly:
successfield allows easy response type detection - Extensibility:
detailsfield supports arbitrary error context - Standards Compliance: Follows REST API best practices
Clients must update their response parsing logic:
Before:
// Success
const streamId = response.id;
const timestamp = response.timestamp;
// Error
const errorCode = response.error.code;After:
// Success
if (response.success) {
const streamId = response.data.id;
const timestamp = response.meta.timestamp;
}
// Error
if (!response.success) {
const errorCode = response.error.code;
}- Check the
successfield to determine response type - Access data through
response.datafor successful responses - Access metadata through
response.meta(timestamp, requestId) - Access error details through
response.errorfor error responses - Update error code comparisons to use
UPPER_SNAKE_CASE
All tests have been updated to verify:
- ✅ Success responses have correct envelope structure
- ✅ Error responses have correct envelope structure
- ✅
requestIdis included when available - ✅
timestampis valid ISO-8601 format - ✅
successfield correctly indicates response type - ✅ Decimal string serialization guarantees are preserved
src/utils/response.ts- Response envelope helperssrc/middleware/errorHandler.ts- Error handler middlewaresrc/routes/streams.ts- Streams API routessrc/routes/audit.ts- Audit log routessrc/routes/dlq.ts- Dead-letter queue routessrc/routes/indexer.ts- Indexer routessrc/routes/webhooks.ts- Webhook routessrc/app.ts- Application setup and 404 handler
tests/helpers.test.ts- Response envelope helper teststests/routes/streams.test.ts- Streams route teststests/routes/health.test.ts- Health route tests
API_BEHAVIOR.md- API behavior specificationopenapi.yaml- OpenAPI specification
Run the following commands to verify the implementation:
# Type check
npx tsc --noEmit
# Run tests
npm test
# Check specific test files
npm test -- tests/helpers.test.ts
npm test -- tests/routes/streams.test.ts
npm test -- tests/routes/health.test.ts- Update API client libraries to handle new envelope structure
- Update API documentation and examples
- Communicate breaking changes to API consumers
- Consider versioning strategy (e.g.,
/v2/api/streams) - Monitor error logs for any missed edge cases
The standardized error envelope implementation provides a consistent, predictable API surface that improves developer experience and makes the API easier to consume. All routes now follow the same response structure, with comprehensive test coverage and updated documentation.