Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
162 commits
Select commit Hold shift + click to select a range
7bb1bc8
feat: address requested issues - closes #264, closes #263, closes #26…
aetheron06 Sep 28, 2026
899d425
feat: Add comprehensive observability, security, and simulation impro…
tecch-wiz Sep 28, 2026
9ff2d4e
feat(workers): centralize job error handling with scrubbed structured…
AdaBebe0 Sep 28, 2026
54c6a43
feat(pagination): add offset/limit pagination to list endpoints
Deb-Auth Sep 29, 2026
70fbd2c
Merge branch 'main' into feature/issues-261-264-draft
gelluisaac Sep 29, 2026
8f4c8b1
Merge branch 'main' into feat/344-offset-limit-pagination
Deb-Auth Sep 29, 2026
297797a
feat(filters): add GlobalExceptionFilter with Prisma and validation e…
IyanuOluwaJesuloba Sep 29, 2026
097a21c
Batch dashboard queries and add activity log pagination test coverage…
davidugorji Sep 29, 2026
7570688
feat(filters): add GlobalExceptionFilter with Prisma and validation e…
IyanuOluwaJesuloba Sep 29, 2026
2a4d8c6
Fix #234: Implement Event Emitter Domain Event Handlers for Transacti…
CodeOtsutsuki007 Sep 29, 2026
25f715e
Fix #225: Implement Structured Audit Log Interceptor for Mutating Ope…
helloworld1-star Sep 29, 2026
b958b3d
Fix #223: Implement Stellar Transaction Simulation Service Integratio…
helloworld1-star Sep 29, 2026
1aa0862
Fix #226: Add Redis-Backed Rate Limiting Guard with Dynamic Tier Supp…
helloworld1-star Sep 29, 2026
3db597e
Fix #231: Implement Redis-backed Rate Limiting Guard for Sensitive AP…
helloworld1-star Sep 29, 2026
dcfa657
feat(interceptors): add global RequestIdInterceptor for correlation l…
IyanuOluwaJesuloba Sep 29, 2026
fc1bf00
feat(throttler): add Redis-backed rate limiting guard and throttler c…
IyanuOluwaJesuloba Sep 29, 2026
2480167
Add startup migration check and DB pool connection metrics
dslegacy Sep 28, 2026
d49abf1
Fix CI: document missing env vars, fix flaky retry backoff test
Depo-dev Sep 29, 2026
f9dd101
Fix pre-existing typecheck/lint/test failures blocking CI
dslegacy Sep 29, 2026
9db725d
Fix remaining pre-existing lint errors and undocumented env vars
dslegacy Sep 29, 2026
ff348aa
perf(auth): cache session revocation answers during token verification
samad13 Sep 29, 2026
d603adc
feat: correlate requests, paginate audit, sign webhooks
aetheron06 Sep 29, 2026
e0e4c99
feat(rate-limit): configurable limits and client identifiers for publ…
samad13 Sep 29, 2026
af4dd17
feat: stream audit exports and harden payment safety (#63, #64, #283)
aetheron06 Sep 30, 2026
28863d9
fix: validate nested transaction metadata as JSON (#283)
aetheron06 Sep 30, 2026
afd2c40
feat(transactions): implement agent spending limit evaluation guard
IyanuOluwaJesuloba Sep 30, 2026
8e3c3a9
Merge branch 'main' into feat/agent-spending-limit-guard
IyanuOluwaJesuloba Sep 30, 2026
fdf5624
fix(ci): resolve typecheck and lint failures across specs, guards, an…
samad13 Sep 30, 2026
93e48b3
fix(ci): resolve typecheck and lint failures across specs, guards, an…
samad13 Sep 30, 2026
bc7be64
fix(config): deduplicate parseClientIdentifiers and pass the raw vari…
samad13 Sep 30, 2026
53fb18a
feat(audit): implement structured audit logging interceptor for sensi…
tecch-wiz Sep 30, 2026
2907886
refactor(policies): add Prisma repository abstraction for agent spend…
tecch-wiz Sep 30, 2026
67a6e23
feat(webhooks): add BullMQ retry policy and dead-letter audit for web…
tecch-wiz Sep 30, 2026
cc2cd00
feat(rate-limit): add Redis-backed agent throttler guard for high-fre…
tecch-wiz Sep 30, 2026
994f233
Fix CI: pre-existing typecheck/lint/test breakage inherited from main
Depo-dev Sep 30, 2026
5f2b0bb
Merge pull request #372 from dslegacy/feat/cache-migration-pool-impro…
Cjay-Cyber-2 Sep 30, 2026
85bbfc6
Merge branch 'main' into feat/query-metrics-batch-recovery-validation…
Depo-dev Sep 30, 2026
1e96bb3
Fix CI: repair botched merge of main into this branch
Depo-dev Sep 30, 2026
01be6da
Merge origin/main into feat/342-public-route-rate-limits
Oct 1, 2026
6d65e86
Merge origin/main into feat/341-token-verification-cache
Oct 1, 2026
45873ce
Merge origin/main into fix/340-worker-error-handling
Oct 1, 2026
1883a0e
Remove conflict markers from worker merge
Oct 1, 2026
9a4ad27
Merge pull request #392 from samad13/feat/342-public-route-rate-limits
Cjay-Cyber-2 Oct 1, 2026
91dbf65
Merge branch 'main' into feat/341-token-verification-cache
Cjay-Cyber-2 Oct 1, 2026
fa66f5b
Merge pull request #391 from samad13/feat/341-token-verification-cache
Cjay-Cyber-2 Oct 1, 2026
9c6ce12
feat: implement risk scoring persistence and complete API documentation
xeladev4 Sep 28, 2026
2819c4a
fix: add missing relation field in RiskAssessment model
xeladev4 Sep 28, 2026
14b46bc
fix: resolve TypeScript errors in test files
xeladev4 Sep 28, 2026
8a95365
fix: add null checks for toPromise() results in response interceptor …
xeladev4 Sep 28, 2026
b3af788
fix: add eslint-disable comments for temporary any types
xeladev4 Sep 28, 2026
ea5d156
fix: update test expectation for date comparison in statistics test
xeladev4 Sep 28, 2026
ba993d2
fix: remove duplicate Zod validation pipe integration test
xeladev4 Oct 1, 2026
f4ac489
Merge origin/main into feature/risk-scoring-swagger-zod-response-enve…
xeladev4 Oct 2, 2026
3821802
Merge pull request #284 from xeladev4/feature/risk-scoring-swagger-zo…
Cjay-Cyber-2 Oct 2, 2026
2489e7c
Merge branch 'main' into feature/issues-261-264-draft
gelluisaac Oct 2, 2026
ec128ad
Merge branch 'main' into feature/issues-55-57-61
aetheron06 Oct 2, 2026
ccc549b
fix ci
gelluisaac Oct 2, 2026
56a6b48
fix ci
gelluisaac Oct 2, 2026
664a65e
fix failing ci
gelluisaac Oct 2, 2026
5afeaa2
fix ci
gelluisaac Oct 2, 2026
dc3e3c2
Merge branch 'main' into build/complete-issues-63-64-283
eliasaph01 Oct 2, 2026
3b11de3
fix ci
aetheron06 Oct 2, 2026
939b1b9
Merge branch 'main' into feat/agent-spending-limit-guard
IyanuOluwaJesuloba Oct 2, 2026
3fd0357
fix ci
aetheron06 Oct 2, 2026
0524bf9
feat: add RiskRepository, RiskAssessment schema, and Swagger decorato…
Cjay-Cyber-2 Sep 29, 2026
eec5b3f
feat: address requested issues - Done with all issues (#357)
DarcKnight000 Sep 29, 2026
9b2c9b8
feat(health): dedicated GET /health/redis probe (#358)
oladeeayo Sep 29, 2026
091e831
test(auth): lock in auth throttle-tier wiring on public routes (#359)
0xDeon Sep 29, 2026
a1381af
feat(health): add /health/live and /health/ready probes (#362)
AdaBliss Sep 29, 2026
a789e1a
feat(config): validate full environment at startup (#363)
AdaBliss Sep 29, 2026
b7d7141
fix(tests): add SpendingLimitService mock to TransactionService spec
IyanuOluwaJesuloba Oct 2, 2026
8d2ea73
feat: webhook ingress validation, retry queue cleanup, rate limiting …
Johnalex-hub Sep 29, 2026
2dd724d
feat: add production rollback protection to database migration CLI (#…
AdaBebe0 Sep 29, 2026
8c8d097
test: add full branch coverage tests for role, permission and scope g…
AdaBebe0 Sep 29, 2026
b68a286
perf: add concurrent composite indexes for notification, approval and…
AdaBebe0 Sep 29, 2026
648ec16
feat: add IP-based rate limiting to public endpoints (#377)
Deb-Auth Sep 29, 2026
9271b31
feat: return RFC 9457 problem details for all error responses (#378)
Deb-Auth Sep 29, 2026
f9861ad
fix: worker error handling + log scrubbing (#370)
Cjay-Cyber-2 Sep 29, 2026
bfdfd2f
feat: query metrics, retry utility, and input sanitization (resolve P…
Cjay-Cyber-2 Sep 29, 2026
00baabf
Batch dashboard queries and add activity log pagination test coverage…
davidugorji Sep 29, 2026
8779101
feat(filters): add GlobalExceptionFilter with Prisma and validation e…
IyanuOluwaJesuloba Sep 29, 2026
f3aace6
Fix #234: Implement Event Emitter Domain Event Handlers for Transacti…
CodeOtsutsuki007 Sep 29, 2026
52f9780
Fix #225: Implement Structured Audit Log Interceptor for Mutating Ope…
helloworld1-star Sep 29, 2026
e7bc633
Fix #223: Implement Stellar Transaction Simulation Service Integratio…
helloworld1-star Sep 29, 2026
af79c21
Fix #226: Add Redis-Backed Rate Limiting Guard with Dynamic Tier Supp…
helloworld1-star Sep 29, 2026
c4c48a0
Fix #231: Implement Redis-backed Rate Limiting Guard for Sensitive AP…
helloworld1-star Sep 29, 2026
bda24eb
feat(interceptors): add global RequestIdInterceptor for correlation l…
IyanuOluwaJesuloba Sep 29, 2026
122abfd
feat(throttler): add Redis-backed rate limiting guard and throttler c…
IyanuOluwaJesuloba Sep 29, 2026
73af4c6
fix: resolve rebase conflicts and restore CI
Oct 2, 2026
1b1281d
Merge remote-tracking branch 'upstream/main' into feat
Oct 2, 2026
03b753a
feat: implement risk scoring persistence and complete API documentation
xeladev4 Sep 28, 2026
fbd3fa4
fix: add missing relation field in RiskAssessment model
xeladev4 Sep 28, 2026
ef79892
fix: resolve TypeScript errors in test files
xeladev4 Sep 28, 2026
0da8cf0
fix: add null checks for toPromise() results in response interceptor …
xeladev4 Sep 28, 2026
235c34d
fix: add eslint-disable comments for temporary any types
xeladev4 Sep 28, 2026
5d78314
fix: update test expectation for date comparison in statistics test
xeladev4 Sep 28, 2026
596a4e2
fix: remove duplicate Zod validation pipe integration test
xeladev4 Oct 1, 2026
36dfc52
feat: add RiskRepository, RiskAssessment schema, and Swagger decorato…
Cjay-Cyber-2 Sep 29, 2026
c05bbfa
feat: address requested issues - Done with all issues (#357)
DarcKnight000 Sep 29, 2026
e119287
feat(health): dedicated GET /health/redis probe (#358)
oladeeayo Sep 29, 2026
53634e0
test(auth): lock in auth throttle-tier wiring on public routes (#359)
0xDeon Sep 29, 2026
3b221aa
feat(health): add /health/live and /health/ready probes (#362)
AdaBliss Sep 29, 2026
f405453
feat(config): validate full environment at startup (#363)
AdaBliss Sep 29, 2026
87ede98
feat: webhook ingress validation, retry queue cleanup, rate limiting …
Johnalex-hub Sep 29, 2026
88c4499
feat: add production rollback protection to database migration CLI (#…
AdaBebe0 Sep 29, 2026
148883f
test: add full branch coverage tests for role, permission and scope g…
AdaBebe0 Sep 29, 2026
893cdb5
perf: add concurrent composite indexes for notification, approval and…
AdaBebe0 Sep 29, 2026
ecf1ef5
feat: add IP-based rate limiting to public endpoints (#377)
Deb-Auth Sep 29, 2026
44d6de3
feat: return RFC 9457 problem details for all error responses (#378)
Deb-Auth Sep 29, 2026
d081e07
fix: worker error handling + log scrubbing (#370)
Cjay-Cyber-2 Sep 29, 2026
9432a5e
feat: query metrics, retry utility, and input sanitization (resolve P…
Cjay-Cyber-2 Sep 29, 2026
4a59842
Batch dashboard queries and add activity log pagination test coverage…
davidugorji Sep 29, 2026
e515c0b
feat(filters): add GlobalExceptionFilter with Prisma and validation e…
IyanuOluwaJesuloba Sep 29, 2026
36a236f
Fix #234: Implement Event Emitter Domain Event Handlers for Transacti…
CodeOtsutsuki007 Sep 29, 2026
042b8b6
Fix #225: Implement Structured Audit Log Interceptor for Mutating Ope…
helloworld1-star Sep 29, 2026
caad35c
Fix #223: Implement Stellar Transaction Simulation Service Integratio…
helloworld1-star Sep 29, 2026
680b535
Fix #226: Add Redis-Backed Rate Limiting Guard with Dynamic Tier Supp…
helloworld1-star Sep 29, 2026
88cd65c
Fix #231: Implement Redis-backed Rate Limiting Guard for Sensitive AP…
helloworld1-star Sep 29, 2026
b13fb7f
feat(interceptors): add global RequestIdInterceptor for correlation l…
IyanuOluwaJesuloba Sep 29, 2026
962847b
feat(throttler): add Redis-backed rate limiting guard and throttler c…
IyanuOluwaJesuloba Sep 29, 2026
4057e17
Add startup migration check and DB pool connection metrics
dslegacy Sep 28, 2026
030bb12
Fix pre-existing typecheck/lint/test failures blocking CI
dslegacy Sep 29, 2026
811093f
Fix remaining pre-existing lint errors and undocumented env vars
dslegacy Sep 29, 2026
677d030
perf(auth): cache session revocation answers during token verification
samad13 Sep 29, 2026
3409515
fix(ci): resolve typecheck and lint failures across specs, guards, an…
samad13 Sep 30, 2026
acccde2
feat(rate-limit): configurable limits and client identifiers for publ…
samad13 Sep 29, 2026
8bbdf2f
fix(ci): resolve typecheck and lint failures across specs, guards, an…
samad13 Sep 30, 2026
5761cbf
fix(config): deduplicate parseClientIdentifiers and pass the raw vari…
samad13 Sep 30, 2026
c284263
Merge remote-tracking branch 'upstream/main' into feat
Oct 2, 2026
9ed44e2
Merge pull request #395 from dakwa001/feat
Cjay-Cyber-2 Oct 2, 2026
8f51df3
Merge origin/main into feat/agent-spending-limit-guard
Oct 2, 2026
30be66a
Provide spending limit dependency in transaction tests
Oct 2, 2026
c91f675
Merge branch 'main' into build/complete-issues-63-64-283
Cjay-Cyber-2 Oct 2, 2026
c08eea1
Merge pull request #394 from IyanuOluwaJesuloba/feat/agent-spending-l…
Cjay-Cyber-2 Oct 2, 2026
62e9bfe
Merge branch 'main' into build/complete-issues-63-64-283
Cjay-Cyber-2 Oct 2, 2026
7a1d04c
Merge pull request #393 from eliasaph01/build/complete-issues-63-64-283
Cjay-Cyber-2 Oct 2, 2026
28bdce0
Merge branch 'main' into fix/340-worker-error-handling
Cjay-Cyber-2 Oct 2, 2026
67e6564
Merge branch 'main' into feature/issues-257-260-draft
Cjay-Cyber-2 Oct 2, 2026
9a008ca
Merge pull request #370 from AdaBebe0/fix/340-worker-error-handling
Cjay-Cyber-2 Oct 2, 2026
69269ae
Merge branch 'main' into feature/issues-257-260-draft
Cjay-Cyber-2 Oct 2, 2026
e86bfef
Merge pull request #361 from efuncode/feature/issues-257-260-draft
Cjay-Cyber-2 Oct 2, 2026
4eeb222
Merge origin/main into PR 390
Oct 2, 2026
68ab564
Merge origin/main into PR 368
Oct 2, 2026
8b87b8b
Fix merged audit repository test structure
Oct 2, 2026
be2238c
Merge origin/main into PR 366
Oct 2, 2026
c2fe86d
Merge origin/main into PR 360
Oct 2, 2026
0cef35a
Fix merged API audit and webhook tests
Oct 2, 2026
962b3d7
Align policy velocity test with service architecture
Oct 2, 2026
aca42eb
Merge pull request #368 from Depo-dev/feat/query-metrics-batch-recove…
Cjay-Cyber-2 Oct 2, 2026
ce6f49c
Merge latest origin/main into PR 366
Oct 2, 2026
3886554
Merge latest origin/main into PR 390
Oct 2, 2026
2bed942
Merge latest origin/main into PR 360
Oct 2, 2026
889d598
Merge pull request #366 from tecch-wiz/feat
Cjay-Cyber-2 Oct 2, 2026
22df50b
Preserve webhook failure reason in audit
Oct 2, 2026
b29771e
Merge latest origin/main into PR 390
Oct 2, 2026
7eae744
Merge latest origin/main into PR 360
Oct 2, 2026
2089a5e
Merge pull request #390 from aetheron06/feature/issues-55-57-61
Cjay-Cyber-2 Oct 2, 2026
87ecea8
Resolve latest API main conflicts in PR 360
Oct 2, 2026
10b5c25
Fix duplicate event emitter declarations
Oct 2, 2026
1d3871d
Merge pull request #360 from gelluisaac/feature/issues-261-264-draft
Cjay-Cyber-2 Oct 2, 2026
7e3c6e0
Merge origin/main into PR 376
Oct 3, 2026
00077ea
Fix typecheck breakage left by merging main into the pagination PR
Deb-Auth Oct 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ QUEUE_CONCURRENCY=5
# Counters are stored in Redis so every API replica enforces the same budget.
THROTTLE_AUTH_LIMIT=10
THROTTLE_API_LIMIT=120
# Per-agent tier: agent-identified traffic (x-agent-id / agent-bound API keys).
THROTTLE_AGENT_LIMIT=300
THROTTLE_WEBHOOK_LIMIT=30
THROTTLE_TTL=60
# Burst limits — short-term spike allowance per tier (requests per second)
Expand Down
86 changes: 76 additions & 10 deletions API_DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ List wallets for the organization.
**Query Parameters:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| page | number | No | Page number (default: 1) |
| limit | number | No | Items per page (default: 10) |
| offset | number | No | Rows to skip (default: 0); mutually exclusive with `page` |
| page | number | No | Page number, alternative to `offset` (default: 1) |
| limit | number | No | Items per page (default: 50, max: 200) |

**Authentication:** Bearer token required

Expand Down Expand Up @@ -168,8 +169,9 @@ List transactions for the organization.
**Query Parameters:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| page | number | No | Page number (default: 1) |
| limit | number | No | Items per page (default: 10) |
| offset | number | No | Rows to skip (default: 0); mutually exclusive with `page` |
| page | number | No | Page number, alternative to `offset` (default: 1) |
| limit | number | No | Items per page (default: 50, max: 200) |

**Authentication:** Bearer token required

Expand Down Expand Up @@ -228,8 +230,9 @@ List policies for the organization.
**Query Parameters:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| page | number | No | Page number (default: 1) |
| limit | number | No | Items per page (default: 10) |
| offset | number | No | Rows to skip (default: 0); mutually exclusive with `page` |
| page | number | No | Page number, alternative to `offset` (default: 1) |
| limit | number | No | Items per page (default: 50, max: 200) |

**Authentication:** Bearer token required

Expand Down Expand Up @@ -322,8 +325,9 @@ List budgets for the organization.
**Query Parameters:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| page | number | No | Page number (default: 1) |
| limit | number | No | Items per page (default: 10) |
| offset | number | No | Rows to skip (default: 0); mutually exclusive with `page` |
| page | number | No | Page number, alternative to `offset` (default: 1) |
| limit | number | No | Items per page (default: 50, max: 200) |

**Authentication:** Bearer token required

Expand Down Expand Up @@ -372,6 +376,51 @@ Delete a budget.

---

## Request Correlation

Every response includes the selected request ID in the `x-request-id` header and the standard response envelope. A caller-supplied ID is accepted only when it is 1-128 ASCII characters, starts with a letter or digit, and otherwise contains only letters, digits, `.`, `_`, `:`, or `-`. Invalid values are replaced with a server-generated UUID. The selected ID is propagated as typed event/job metadata and is isolated per concurrent request.

## Audit History (`/audit`)

### GET `/audit`
List audit records in reverse chronological order using a stable `(createdAt, id)` keyset.

**Query Parameters:** `limit` defaults to 20 and is bounded to 1-100; `cursor` is the opaque `nextCursor` from the previous response; optional `actorId`, `action`, `resourceId`, `from`, and `to` filters apply within the authenticated organization. `from` and `to` are inclusive ISO 8601 timestamps and `from` must not be later than `to`.

The response `meta` includes `limit`, `hasNext`, and `nextCursor` (null on the final page). New records inserted after a page is read do not shift subsequent pages.

**Example:** `GET /audit?limit=20&actorId=user-123&action=wallet.created`

## Outbound Webhook Signatures

Webhook creation and secret rotation responses disclose the signing secret once. Later list, get, update, delivery, and audit responses never include it. Store the secret securely and rotate it when compromised.

Every delivery includes `x-astroid-signature`, `x-astroid-signature-version`, `x-astroid-timestamp`, and `x-astroid-event-id`. `x-astroid-delivery` remains an alias for the event ID. The signature header is `v1=<lowercase hex HMAC-SHA256>` and the version header is `v1`.

The canonical signed bytes are UTF-8 `v1.<timestamp>.<event-id>.` followed by the exact raw HTTP body bytes. Each retry uses the same event ID and body, with a fresh timestamp and signature. Consumers should also reject timestamps outside their chosen replay window.

```js
import { createHmac, timingSafeEqual } from 'node:crypto';

export function verifyAstroidWebhook({ secret, headers, rawBody }) {
const version = headers['x-astroid-signature-version'];
const timestamp = headers['x-astroid-timestamp'];
const eventId = headers['x-astroid-event-id'];
const received = headers['x-astroid-signature'];
if (version !== 'v1' || !/^\d{1,12}$/.test(timestamp) || !eventId) return false;
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;

const prefix = Buffer.from(`v1.${timestamp}.${eventId}.`, 'utf8');
const expected = createHmac('sha256', secret)
.update(Buffer.concat([prefix, rawBody]))
.digest();
const match = /^v1=([0-9a-f]{64})$/.exec(received);
if (!match) return false;
const actual = Buffer.from(match[1], 'hex');
return actual.length === expected.length && timingSafeEqual(actual, expected);
}
```

## Health Probes (`/health`)

The liveness and readiness probes are served **outside** the API prefix, so
Expand Down Expand Up @@ -424,10 +473,27 @@ under the API prefix at `GET /{API_PREFIX}/health/readiness`,
## Common Types

### Pagination Query
Every list endpoint accepts the same query parameters.

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| page | number | 1 | Page number |
| limit | number | 10 | Items per page |
| offset | number | 0 | Zero-based number of rows to skip. Mutually exclusive with `page` |
| page | number | 1 | 1-based page number, an alternative to `offset` |
| limit | number | 50 | Items per page, capped at 200 |
| sort | string | createdAt | Sort field (restricted to an allow-list per endpoint) |
| order | `asc` \| `desc` | desc | Sort direction |

Negative, non-integer or non-numeric values, a `limit` above 200, or supplying both `offset` and `page` return `400 Bad Request`.

Paginated responses carry the total row count in the `X-Total-Count` header and in `meta`:
```json
{
"success": true,
"data": [],
"meta": { "offset": 50, "page": 2, "limit": 50, "total": 120, "totalPages": 3, "hasNext": true, "hasPrev": true },
"requestId": "req_..."
}
```

### Error Response
All endpoints return errors as [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) problem details with `Content-Type: application/problem+json`:
Expand Down
Loading
Loading