diff --git a/README.md b/README.md index 1046cd1f..1c407272 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,44 @@ API gateway, usage metering, and billing services for the Callora API marketplace. Talks to Soroban contracts and Horizon for on-chain settlement. +## Logs Endpoint + +Authenticated users can submit and retrieve structured log entries via `/api/logs`. + +- `GET /api/logs` — Retrieve all log entries for the authenticated user, sorted newest-first. + Returns `{ data: { logs: [...], meta: { total } } }` in the canonical success envelope. +- `POST /api/logs` — Submit a new log entry. + Body: `{ "message": string, "level"?: "debug"|"info"|"warn"|"error", "meta"?: object }`. + Returns `201` with the created entry. + +### Rate Limiting + +Both endpoints are protected by a **per-user token-bucket** rate limiter. + +| Variable | Default | Description | +|---|---|---| +| `LOGS_RATE_LIMIT_CAPACITY` | `60` | Burst ceiling (tokens per user) | +| `LOGS_RATE_LIMIT_REFILL_RATE` | `1` | Tokens refilled per second | + +When the bucket empties the server immediately responds with: + +``` +HTTP/1.1 429 Too Many Requests +Retry-After: + +{ + "code": "TOO_MANY_REQUESTS", + "message": "Too Many Requests", + "requestId": "...", + "retryAfterMs": 750 +} +``` + +Key resolution (priority order): +1. Authenticated user ID from the JWT `Authorization: Bearer` header. +2. `x-user-id` header (trusted internal/test header). +3. Client IP address (unauthenticated fallback). + ## API Catalog Pagination (`GET /api/apis`) The public API catalog endpoint uses **keyset cursor pagination** over `(created_at DESC, id DESC)` for stable, gap-free traversal under concurrent writes. Offset-based pagination has been removed; all requests now return cursor-based responses. diff --git a/src/routes/index.ts b/src/routes/index.ts index 94d2a96b..579e0b15 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -76,6 +76,10 @@ export function createApiRouter(deps: ApiRouterDeps = {}): Router { router.use("/audit", createAuditRouter({ auditService: deps.auditService })); router.use("/invoices", createInvoicesRouter()); + // Logs — per-user structured log ingestion and retrieval, rate-limited via + // a token-bucket limiter (see src/routes/logs.ts and LOGS_RATE_LIMIT_* env vars). + router.use("/logs", createLogsRouter()); + router.use( "/apis", createApisRouter({