Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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: <seconds>

{
"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.
Expand Down
4 changes: 4 additions & 0 deletions src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
Loading