Client Error Reporting Endpoint
Version: 1.1.0 Date: 2026-07-15
Goal: Allow front-end applications (IP Magic Box, Tower, etc.) to report client-side errors to the backend for centralized monitoring, support triage, and error-catalog matching.
Solution: New client-errors domain with a throttled POST endpoint for error creation and a GET endpoint (admin-only) for querying errors with filters and pagination.
API contract
POST /api/v2/client-errors
Auth: Bearer API token (same as other neo routes).
Headers:
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <api-token> |
Bcyip-Agent | No | Source identifier (e.g. ipmagicbox, iptower). Defaults to unknown if omitted. |
Content-Type | Yes | application/json |
Rate limit: 60 requests/minute per IP (ThrottlerGuard).
Request body (CreateClientErrorDto):
{
"appVersion": "4.37.0",
"taskType": "Upload",
"error": [
{
"name": "FileUploadError",
"message": "Could not upload file to Sharepoint",
"stack": "FileUploadError: ...",
"code": "optional-string"
}
],
"context": {
"os": "darwin",
"arch": "arm64",
"fileName": "contract.pdf",
"fileSize": 1048576
}
}
| Field | Type | Required | Notes |
|---|---|---|---|
appVersion | string | Yes | Client semver (IP Magic Box package.json version) |
taskType | string | No | Pipeline stage when error occurred (e.g. Upload, Anchor) |
error | array | Yes | Min 1 item. Serialized error chain — see IP Magic Box IPBError.serialize() |
context | object | No | Free-form diagnostic context (OS, file metadata, hash, etc.) |
Each error[] item (IP Magic Box convention):
| Field | Type | Required |
|---|---|---|
name | string | Yes |
message | string | Yes |
stack | string | Yes |
code | string | No |
Nested causes are additional array elements (outer error first, cause chain flattened).
Response: 201 — MongoDB insertedId (ObjectId string).
Stored document (server-enriched):
{
"appVersion": "4.37.0",
"taskType": "Upload",
"error": [ "..." ],
"context": { "..." },
"userId": "<ObjectId>",
"jobId": "<ObjectId>",
"companyRef": "<ObjectId>",
"source": "ipmagicbox",
"createdAt": "2026-07-15T12:00:00.000Z"
}
GET /api/v2/client-errors (admin only)
Auth: Bearer token with Role.Admin.
Query params (QueryClientErrorDto):
| Param | Type | Default | Description |
|---|---|---|---|
companyRef | ObjectId string | — | Filter by company |
userId | ObjectId string | — | Filter by user |
source | string | — | Filter by Bcyip-Agent value |
taskType | string | — | Filter by task stage |
dateFrom | ISO date string | — | createdAt >= |
dateTo | ISO date string | — | createdAt <= |
page | number | 1 | Page index |
limit | number | 50 | Page size |
Response: { items: ClientError[], total: number, page, limit }
Implementation Details
- Collection:
clientErrors - TTL index on
createdAt— auto-delete after 90 days (expireAfterSeconds: 7776000) - Compound indexes:
{ companyRef, createdAt },{ source, createdAt },{ userId, createdAt } - IP Magic Box: fire-and-forget
reportClientError()with per-task deduplication (reportedErrorTaskIds)
Files Modified:
src/domains/client-error/client-error.module.tssrc/domains/client-error/client-error.controller.tssrc/domains/client-error/client-error.service.tssrc/domains/client-error/dto/create-client-error.dto.tssrc/domains/client-error/dto/query-client-error.dto.tssrc/domains/client-error/client-error.service.spec.tssrc/domains/client-error/client-error.controller.spec.ts
Release fragment: feat-client-error-endpoint