Public subscription and feed endpoints
| Route | Method | Access | Purpose |
|---|---|---|---|
/api/subs/new?calendar_id=programs | POST | Public; Turnstile when configured | Create a 30-minute verification request and send a magic link |
/api/subs/new?calendar_id=internal | POST | Internal boundary | Forward the legacy Internal subscription request to n8n |
/api/subs/verify?calendar_id=programs&v=... | GET | One-time magic link | Consume the verification request and issue a private feed token |
/api/turnstile-site-key | GET | Public | Return the configured public Turnstile site key |
/cal/programs.ics?calendar_id=programs&token=... | GET/HEAD | Calendar token | Validate the token hash and serve programs.ics from R2 |
/cal/internal.ics | GET/HEAD | Internal boundary | Proxy the legacy Internal feed to n8n |
Invalid, expired, disabled, or revoked feed tokens use non-revealing error behavior so calendar clients do not learn why a token failed.
Renewal
| Route | Method | Access | Purpose |
|---|---|---|---|
/renew?rt=... | GET | Signed renewal credential | Render a confirmation page without changing data |
/extend | GET | Existing saved links | Redirect to the current renewal flow |
/api/subs/extend | POST | Signed credential; legacy raw token accepted for old email | Extend the token row and reset warning state |
The rt value is not a calendar token. It is an expiring HMAC-signed token-row id and cannot be used at /cal/programs.ics.
Webhook and scheduled endpoints
| Route | Method | Access | Purpose |
|---|---|---|---|
/api/webhooks/resend | POST | Valid Svix signature | Record delivered, bounced, or complained email outcomes |
/api/cron/regenerate-programs-ics | POST | CRON_BEARER_TOKEN | Query selected Notion events and rebuild R2 when bytes changed |
/api/cron/renewal-warnings | POST | CRON_BEARER_TOKEN | Send the 14-day and 3-day renewal warnings |
Admin authorization
All routes below pass through one directory-level middleware. It verifies the Cloudflare Access JWT, maps the request to an action, and asks RC Console whether the caller’s current Calendar role contains that action.
sequenceDiagram participant Browser participant Calendar participant Policy as RC Console policy service Browser->>Calendar: Admin request + Access session Calendar->>Calendar: Verify JWT and map route to action Calendar->>Policy: Check person + calendar + action Policy-->>Calendar: Explicit allow or deny Calendar-->>Browser: Continue or 403
Unmapped routes and policy-service errors fail closed.
Admin action map
| Route | Method | Action |
|---|---|---|
/api/admin/stats | GET | stats.read |
/api/admin/events | GET | events.read |
/api/admin/activity | GET | activity.read |
/api/admin/funnel | GET | funnel.read |
/api/admin/cohort | GET | cohort.read |
/api/admin/latency | GET | latency.read |
/api/admin/health | GET | health.read |
/api/admin/replay | GET | replay.read |
/api/admin/subs/list | GET | subscribers.list |
/api/admin/subs/:id | GET | subscriber.read |
/api/admin/enable | POST | subscriber.enable |
/api/admin/revoke | POST | subscriber.revoke |
/api/admin/token-extend | POST | token.extend |
/api/admin/bulk-extend | POST | token.bulk_extend |
/api/admin/token-resend | POST | token.resend |
/api/admin/token-force-expire | POST | token.force_expire |
/api/admin/test-email | POST | email.test |
/api/admin/templates/:id | GET | template.read |
/api/admin/templates/:id | PUT | template.edit |
/api/admin/templates/:id | DELETE | template.reset |
/api/admin/templates/footer | GET | template.read |
/api/admin/templates/footer | PUT | template.edit |
/api/admin/templates/footer | DELETE | template.reset |
/api/admin/templates/preview | POST | template.read |
templates/preview accepts unsaved draft fields and renders them through the same generator used for delivered mail. It is a read action even though the request is POST. The shared footer endpoint manages reply text, support text, copyright, and the affiliation disclaimer.
Sources
ihnyc-rc-cal-landing/functions/_lib/route-actions.tsihnyc-rc-cal-landing/functions/api/admin/_middleware.tsihnyc-rc-cal-landing/functions/_lib/pdp-client.tsihnyc-rc-cal-landing/functions/_lib/renew-link.ts- route handlers under
ihnyc-rc-cal-landing/functions/api/