Internals (for contributors)¶
How the developer API is put together, for people changing it rather than calling it. Everything above this page is written for API consumers; this page is not.
Module map¶
Module |
Role |
|---|---|
|
Single source of truth for every public endpoint. Drives the OpenAPI generator and these docs. |
|
Pure scope catalog — shared by the API wrapper, the key-creation UI, the OpenAPI generator, and tests. |
|
Pure error taxonomy: |
|
Renders the OpenAPI 3.1 document from the registry. |
|
Key generation and authentication (hashing, scopes, expiry). |
|
The wrapper: IP gate, auth, per-key rate limiting + headers, scope enforcement, idempotency replay, request IDs, and the bound |
|
Shared response shaping + pagination. |
|
Canonical like/comment/bookmark/follow/post mutations — counters, SSE, notifications, XP, quests, achievements, webhooks. |
|
Pure HMAC signing + the SSRF guard for outbound delivery URLs. |
|
Event catalog. |
|
Delivery + retry drain. |
|
The routes themselves. |
|
Key management endpoints behind the |
lib/api/registry.ts, lib/api/scopes.ts, lib/api/errors.ts and lib/webhooks/events.ts are pure — no server imports, no side effects. That is deliberate: it lets the docs generator, the OpenAPI route, the client-side dashboard, and the unit tests all read the same definitions.
Why engagement mutations are centralised¶
In-app routes and API routes both write posts, likes, comments, bookmarks and follows. Every one of those writes has side effects — counter updates, SSE fanout, notifications, XP, quest progress, achievements, webhook emission. lib/social/engagement.server.ts owns all of it so the two entry points cannot drift: an API-created post awards XP and progresses quests exactly like one from the in-app composer.
Add a side effect there, not in a route handler.
Adding an endpoint¶
Add the route under
app/routes/api/v1/, wrapped inwithDeveloperApi.Add its entry to
ENDPOINTSinlib/api/registry.ts— method, path,operationId, group, scope, params, body fields, and a realisticresponseExample.If it needs a new permission, add it to
SCOPESinlib/api/scopes.ts.Run
pnpm docs:apiand commit the regenerated pages underdocs/developer-api/endpoints/.
Step 4 is checked in CI (pnpm docs:api --check), so a registry change without regenerated docs fails the build rather than shipping a stale reference.
Webhook retry drain¶
The retry queue is drained by POST /api/cron/webhooks, guarded by INTERNAL_API_SECRET. Persistent failures auto-disable the endpoint after the backoff schedule is exhausted (6 attempts).
Where the docs live¶
These pages are the published documentation — there is no longer an in-app wiki. docs/developer-api/*.md is hand-written prose; docs/developer-api/endpoints/*.md is generated by scripts/generate-api-docs.ts and must not be hand-edited. The three reference tables (scopes, errors, webhook events) are spliced into the hand-written guides between <!-- BEGIN GENERATED: … --> markers.