Furries PH Docs
Dashboard
Platform API docs

Route Reference

Event Planning API

Authenticated EPS Preview routes for projects, work, linked personal reminder channels, durable delivery, Sanity artifacts, and canonical EMS commands.

First created Last updated

platform-apievent-planningroutes

Contract

EPS routes are mounted under /api/planning, require dashboard bearer authentication, return camelCase JSON, and validate partner plus project access. EPS is Preview; consumers must tolerate documented contract migrations until General Availability.

The full mounted inventory, method/path map, status vocabulary, version conflicts, idempotency, iCalendar profile, and error semantics are maintained in EPS Data, API, Calendar, and Standards Reference.

Canonical EMS changes

event-catalog reads canonical event, tier, inclusion, add-on, tier-link, and shop tables. change-sets supports organizer-only proposals. canonical-command supports authorized direct edits. Application is atomic, expected-version aware, audited, and idempotent; only a newly applied result schedules the normal Rego publication refresh.

Media contract

POST /projects/:projectId/artifacts uploads to Sanity through the API. Protected content is returned only through /artifacts/:artifactId/content. No response or redirect may expose a Sanity API/CDN URL. Supabase Storage is outside the contract.

Personal reminder channel routes

All user-facing routes below require the dashboard session and re-check project membership. They resolve only the current user’s identity; an administrator cannot link, verify, consent, test, or opt out for someone else.

Method and pathContract
GET /projects/:projectId/my-reminder-channelsReturns mandatory-email status, current personal preferences, masked Telegram/Discord/SMS readiness, test/health timestamps, consent state, gateway summary, and exact cadence. It returns no locator ciphertext, provider ID, token, or full phone number.
POST .../my-reminder-channels/telegram_dm/startCreates a short-lived single-use binding intent for the signed-in linked Telegram identity and the platform bot’s private /start flow.
POST .../telegram_dm/verify, /test, or /unlinkConfirms the matching private chat, sends one redacted test, or revokes the personal binding and pending Telegram attempts.
POST .../my-reminder-channels/discord_dm/start or /verifyResolves the current linked Discord user, creates or reuses a platform-bot DM channel, and verifies DM capability without storing user OAuth tokens for reminder delivery.
POST .../discord_dm/test or /unlinkSends one redacted test or revokes readiness and pending Discord attempts.
POST .../my-reminder-channels/sms/start-verification or /resendNormalizes a candidate E.164 number, enforces challenge bounds and eligible partner SMS transport, then queues an encrypted short-lived verification SMS. Responses remain masked.
POST .../sms/verify, /test, /opt-out, or /unlinkConsumes the digest-stored challenge, records current EPS operational consent, queues one governed test, withdraws consent, or revokes the phone identity and pending SMS attempts.
GET /projects/:projectId/delivery-historyReturns a bounded permission-checked per-channel history using masked targets and safe errors. Filters may narrow channel, state, recipient, and time range.
POST /projects/:projectId/notification-outbox/:outboxId/retryRequeues only an authorized failed/retryable attempt after current identity, project, and destination checks. It does not create a new business reminder.
POST /projects/:projectId/notification-outbox/:outboxId/reconcileReconciles current reminder, outbox, and SMS-job state without rewriting immutable attempt history.

Personal channel preferences use discord_dm, telegram_dm, and sms. Mandatory operational email is independent from enabledChannels, digest, quiet hours, and snooze. Preference updates retain optimistic version checks and must acknowledge the current SMS consent version before enabling SMS.

Scheduler and provider contract

The database creates mandatory email reminders at the canonical cadence, then derives identity-versioned personal channel rows for currently ready opted-in users. Due rows materialize into a unique outbox key. Telegram and Discord locators are decrypted only for their API-owned provider adapter. SMS creates a dedicated encrypted partner-scoped gateway job instead of reusing attendee campaign rows.

Immediately before delivery, the Worker re-checks current project scope, recipient ownership, linked provider uniqueness, personal preference, binding readiness, identity version, SMS verification/consent, and cancellation state. Optional quiet hours or snooze can defer a provider attempt without changing the canonical reminder time. One provider failure never rolls back email or another channel.

Telegram uses the platform bot token. Discord uses the platform bot and restrictive mention behavior. Browsers never submit a personal bot token. Provider responses are reduced to stable safe error codes and bounded retry-after behavior; raw provider response text is not returned or placed in general logs.

Android SMS gateway routes

Native gateway routes authenticate a specific online Android device with a short-lived token returned once at issue/rotation and stored only as a digest:

Method and pathContract
POST /projects/:projectId/sms-gateway/devices/:deviceId/native-tokenAuthorized issue, rotate, or revoke for a same-partner registered device. Revocation releases active leases to safe recovery.
GET /sms-gateway/devices/:deviceId/preflightToken-authenticated online-mode capability, permission, heartbeat, and policy check.
POST /sms-gateway/devices/:deviceId/heartbeatRefreshes bounded health without widening partner or job access.
POST /sms-gateway/devices/:deviceId/leaseLeases eligible same-partner EPS reminder or verification jobs after SIM, country, segment, cost, pacing, expiry, payload-digest, and cancellation-revision checks.
POST /sms-gateway/devices/:deviceId/jobs/:jobId/recheckRe-checks current outbox, identity, consent, payload, and cancellation immediately before native submission.
POST /sms-gateway/devices/:deviceId/jobs/:jobId/receiptRecords idempotent sent, delivered, sent-unconfirmed, failed, or retryable native evidence for the current lease and attempt.

LAN/offline mode cannot call these routes or receive EPS phone payloads. A leased job contains the minimum native send contract; it does not expose unrelated planning data, contact records, or provider credentials. sent_unconfirmed is not promoted to delivered.

Provider delivery does not complete, submit, approve, waive, reject, or otherwise change a task, requirement, meeting, risk, control, or gate.

Completion check

The consumer handles 401, 403, 404, 409 VERSION_CONFLICT, stale identity, consent required, no eligible device/SIM, policy blocked, provider unavailable, lease expired, and retry exhausted states; retains bounded result sets and idempotent replay; and never relies on an upstream Sanity locator or provider secret.

All docs