# Docs - [BIO.RE Developer Portal](/docs): Complete API documentation for the BIO.RE creator monetization platform — 19 modules, 175 endpoints. Every endpoint verified against the live backend (controller + DTO + service + Prisma + live response). - Analytics: Client-side tracking surface — authenticated event tracking + public anonymous session/pageview/heartbeat/leave/identify endpoints. Writes to a separate Analytics DB. GDPR-aware (consent gate, hashed visitorId, no IP storage). - [Track Event](/docs/analytics/track): Authenticated event tracking — emits a FunnelEvent row tied to the current user. Killable via admin config. Validates JSON property payload size. Writes to the main Postgres database, not the Analytics DB. - [Create Analytics Session](/docs/analytics/session-create): Public session-start endpoint. GDPR consent gate, server-side UA + GeoIP, hashed visitorId, HMAC tracking-token requirement when bioPageId is present. Returns null when bot / no consent / forged token. Writes to the separate Analytics DB. - [Record Page View](/docs/analytics/pageview): Public pageview endpoint. Atomic session-counter update, bounce-flag flip on the second view, automatic duration backfill on the previous view. Silently swallows errors. - [Session Heartbeat](/docs/analytics/session-heartbeat): Public keep-alive ping. Updates lastActivityAt and increments duration by a fixed 30 seconds. Designed to fire every 30s while the page is in the foreground. - [Record Page Leave](/docs/analytics/pageview-leave): Public exit-time ping for the LAST pageview of a session — the one that won't get its duration back-filled by a subsequent pageview. Captures duration (capped 1h) and scroll depth (clamped 0-100). Use sendBeacon. - [Identify Session After Login](/docs/analytics/session-identify): Bind the current authenticated userId to a previously-anonymous session id. Idempotent. Lets analytics correlate pre-login traffic with the resulting account. - Authentication: User registration, login, OAuth, 2FA, password reset, sessions, OTP - [Register New Account](/docs/auth/register): Create a new BIO.RE account — email + password + terms acceptance, with optional username, OAuth attribution, and locale. - [Verify Email](/docs/auth/verify-email): Verify a new account's email address using the UUID token from the verification email link. - [Resend Verification Email](/docs/auth/resend-verification): Re-send the email verification link to a registered address. Captcha-gated, low rate limit. - [Login with Email + Password](/docs/auth/login): Authenticate an existing account. Returns JWT access + refresh tokens, OR `requiresTwoFactor` with a temp token. - [Complete Login with 2FA](/docs/auth/login-2fa): Second leg of the 2FA login flow — verify the 6-digit TOTP code (or a backup code) using the temp token from /auth/login. - [Refresh Access Token](/docs/auth/refresh): Exchange a refresh token (from cookie or body) for a new access + refresh JWT pair. Token rotation enforced. - [Logout](/docs/auth/logout): Revoke the current refresh token and invalidate the session. Refresh cookie is cleared. - [Forgot Password](/docs/auth/forgot-password): Request a password reset email. Anti-enumeration — always returns success regardless of account existence. - [Reset Password](/docs/auth/reset-password): Set a new password using the reset token from the email link. Strict rate limit (3/hour). - [Change Password](/docs/auth/change-password): Authenticated password change. Requires current password. All sessions invalidated on success. - [List Active Sessions](/docs/auth/sessions): Get the list of active sessions for the current authenticated user, with device + masked IP + isCurrent flag. - [Revoke Single Session](/docs/auth/session-revoke): Revoke a specific session by ID. Use the session ID from /auth/sessions. Cannot revoke the current session — use logout for that. - [Revoke All Other Sessions](/docs/auth/sessions-revoke-all): Revoke every session except the one making the request. Use this for "Sign out all other devices" UI. - [Current User Identity](/docs/auth/me): Get the current authenticated user's identity (id, email, username, displayName, avatar, status, emailVerified). - [Login or Register via OAuth](/docs/auth/oauth-login): One-step login OR auto-register via Google, Apple, or X (Twitter). No captcha (provider handles bot protection). Server-side token verification. - [List OAuth Login Providers](/docs/auth/oauth-providers): Get the list of currently active OAuth login providers — admin-managed. Frontend uses this to render dynamic Sign-in-with buttons. - [Link OAuth Provider](/docs/auth/oauth-link): Attach an OAuth provider (Google / Apple / X) to the currently authenticated account. Lets users add Sign-in-with after registering with email. - [Unlink OAuth Provider](/docs/auth/oauth-unlink): Remove an OAuth provider link from the current account. Refuses to unlink the only sign-in method (anti-lockout). - [Send Phone OTP](/docs/auth/send-otp): Initiate a 6-digit phone OTP. Creates a Challenge record and dispatches an SMS code via the active SMS provider (admin-managed). Returns challengeId for verify/resend. - [Verify Phone OTP](/docs/auth/verify-otp): Verify the 6-digit OTP code against the Challenge. On success, the Challenge is marked used and the calling flow can advance. - [Resend Phone OTP](/docs/auth/resend-otp): Generate a fresh OTP code, reset attempts, dispatch a new SMS. Caps per challenge + cooldown between resends. - [Get Challenge Metadata](/docs/auth/challenge): Fetch metadata for an active OTP Challenge (masked phone, expiry, remaining attempts). Does NOT return the code. - [Validate Reactivation Token](/docs/auth/reactivate-validate): Pre-flight check for an account reactivation token from an email link. Returns account status without performing reactivation. - [Generate 2FA Setup](/docs/auth/2fa-setup): Start TOTP enrollment. Generates a server-side TOTP secret, encrypts it on the User row, and returns the secret + QR code so the user can pair an authenticator app. - [Init 2FA Setup (Stable Shape)](/docs/auth/2fa-setup-init): Alias of POST /auth/2fa/setup with an explicit recoveryCodes:null contract — kept thin so the frontend type stays stable across setup → verify. - [Verify TOTP & Activate 2FA](/docs/auth/2fa-verify): Verify the 6-digit TOTP code against the previously stored secret. On success, flip 2FA on, generate one-time backup codes, and revoke all existing sessions. - [Disable 2FA](/docs/auth/2fa-disable): Turn 2FA off after re-confirming the account password. Wipes the TOTP secret, deletes all backup codes, and revokes all sessions. - [Regenerate Backup Codes](/docs/auth/2fa-backup-codes-regenerate): Issue a fresh set of backup codes after the user proves their authenticator still works (TOTP code, not backup code). Old codes are deleted atomically. - [Get 2FA Status](/docs/auth/2fa-status): Read whether 2FA is currently enabled on the calling user. Read-only — useful for rendering the right UI on settings screens. - Content: Public CMS pages, blog posts, announcements, help center, FAQ, contact form. Cookie consent management. - [List CMS Pages](/docs/content/pages-list): Public list of admin-managed CMS pages (slug + title + locale + publishedAt). PUBLISHED-only filter — DRAFT and ARCHIVED never leak. CDN-cached 5min/10min SWR. - [Get CMS Page (by slug)](/docs/content/page-by-slug): Public read of a single CMS page by slug. Optional locale selector (default 'en'). HTML body server-side sanitized (script / style / on* / iframe stripped). 404 on missing or DRAFT. - [Get Active Announcements](/docs/content/announcements): Public list of currently-active announcements. Filtered by active flag + time window. Cap 50. Cache 60s. HTML body server-side sanitized. - [List Blog Posts](/docs/content/blog-list): Public paginated list of published blog posts. Optional category filter (by slug). Lightweight items (no body, just excerpt). Categories embedded as { name, slug } pairs. CDN 5min/10min SWR. - [Blog RSS Feed](/docs/content/blog-feed-rss): RSS 2.0 XML feed of the last 20 published blog posts. Content-Type application/rss+xml. Bot-detection skipped (feed readers should not be flagged). CDN 15min/30min SWR. - [Blog Atom Feed](/docs/content/blog-feed-atom): Atom XML feed of the last 20 published blog posts. Same data as the RSS feed in Atom format. Content-Type application/atom+xml. CDN 15min/30min SWR. - [Get Blog Post (by slug)](/docs/content/blog-post): Public read of a single blog post by slug. PUBLISHED-only. HTML body server-side sanitized. Categories embedded as { name, slug } pairs. 404 on missing/draft. - [List Help Categories](/docs/content/help-categories): Public list of published help center categories with article counts. Optional locale filter. Ordered by admin-set sortOrder. CDN 5min/10min SWR. - [List Help Articles](/docs/content/help-articles): Public paginated list of published help articles. Filters by category slug, search term (title/content/excerpt ILIKE), featured-only, locale. Each item carries embedded category. CDN 5min/10min SWR. - [Get Help Article (by slug)](/docs/content/help-article): Public read of a single help article by slug. PUBLISHED-only. HTML body server-side sanitized. Embedded category. 404 on missing/draft. - [Get FAQ](/docs/content/faq): Public list of FAQ groups with their published items. Optional locale filter. Group order is admin-set; items inside each group are admin-ordered too. Answers server-side sanitized. - [Submit Contact Form](/docs/content/contact): Public contact form submission. Captcha-gated (active provider, admin-managed). Captures user-agent + IP server-side. Stores in ContactMessage and fires fire-and-forget admin notification. Hard 3/hour throttle. - [Get Cookie Policy](/docs/content/cookie-policy): Public cookie policy. Returns the 4 cookie categories (essential / functional / analytics / marketing) with localized name and description. - [Get Cookie Consent Status](/docs/content/cookie-status): Public endpoint that works for both anonymous and authenticated users. Returns the current policy version, the user's last-saved version (null for anonymous), and a flag telling the UI whether to re-show the consent banner. - [Save Cookie Consent](/docs/content/cookie-save): Public endpoint to save user's consent choices. Works for anonymous (userId null) and authenticated. Stores under documentType COOKIE_CONSENT with current privacy version. IP captured ONLY when analytics consented (GDPR). - Creator: Onboarding, profile, social accounts, dashboard, bio page, links, DM config, payout, KYC, Stripe Connect, newsletter - [Upgrade to Creator](/docs/creator/upgrade): Convert an authenticated user into a creator. Atomic — creates CreatorProfile + BioPage + flips User.intent to CREATOR. Gated by an admin kill switch. - [Get Creator Profile](/docs/creator/profile): Read the calling creator's full profile — level, KYC, DM pricing, vacation, earnings, Stripe Connect status, bank details, plus the joined BioPage (with links + template), categories, and active DM packages. - [Connect Social Account](/docs/creator/social-connect): Verify a creator's ownership of a social account via OAuth callback. Stores the link plus access/refresh tokens for later platform calls. Recomputes totalFollowers. - [Disconnect Social Account](/docs/creator/social-disconnect): Remove a connected social account. Cascade-deletes the SocialMetrics row and recomputes totalFollowers across the creator's remaining linked accounts. - [List Connected Social Accounts](/docs/creator/social-list): Read up to 50 connected social accounts for the current creator. Returns platform, public username, verification flag, and connection timestamp. OAuth tokens are NOT exposed. - [Get Creator Dashboard](/docs/creator/dashboard): Earnings + level + wallet + DM + response-rate summary in a single response. Computed from CreatorProfile, Wallet, PayoutRequest, Message, SocialAccount, and ConfigService thresholds. - [Get Setup Checklist](/docs/creator/dashboard-checklist): Six-item creator onboarding checklist with completion flags. Static set today (avatar, bio, link, DM config, KYC, social) — drives the post-upgrade getting-started UI. - [Get Recent Activity](/docs/creator/dashboard-activity): Merged feed of the creator's recent messages, processed payouts, and new bio-page subscribers. Three sources combined, sorted by timestamp DESC, sliced to limit. - [Get Bio Page (Editor)](/docs/creator/bio-page): Read the creator's own BioPage row plus its links (ordered) and template. Ownership-checked. Use this for the editor — public fan-side rendering uses GET /bio/:username instead. - [Update Bio Page](/docs/creator/bio-page-update): Sparse update of the BioPage. Bio strips HTML tags, customCss strips XSS vectors, bio body runs through trust-safety content moderation. Cache invalidated on success. - [List Bio Templates](/docs/creator/bio-templates): Public catalog of active bio page templates. CDN-cached (5min). Used in the creator editor to render the template picker. - [Get Public Bio Page (Fan-side)](/docs/creator/bio-public): SSR-friendly public bio page render by username. CDN + in-memory cache, status filter (suspended/banned/deactivated → 404), only published creators with active scheduled links. - [Add Bio Link](/docs/creator/bio-link-add): Append a link to the bio page. Validates URL + scheduling, runs title through moderation, blocks manual social links when DM is active, auto-detects embed type, and respects an admin-managed max-links cap. - [Update Bio Link](/docs/creator/bio-link-update): Sparse update of a bio link. URL revalidation re-runs embed auto-detection. Title HTML-stripped + moderation-checked. Schedule end must follow start. Cache invalidation is best-effort. - [Delete Bio Link](/docs/creator/bio-link-delete): Hard-delete a single bio link by id. Ownership-checked. The owning creator's public bio cache is invalidated; cache lookup failures don't block the delete. - [Reorder Bio Links](/docs/creator/bio-links-reorder): Atomic reordering of bio page links. Submit the full ordered array; sortOrder is set to the array index. Server verifies every linkId belongs to the creator before writing. - [Get Embeddable Bio Page](/docs/creator/bio-embed): Iframe-friendly variant of the public bio render — same payload, but only succeeds when embedEnabled is true. Sets X-Frame-Options ALLOWALL so partner sites can host the iframe. - [Track Bio Page View](/docs/creator/bio-track-view): Append a view record. Server parses User-Agent and resolves country from CDN headers when the client doesn't supply them. Creator-side analytics aggregate from this stream. - [Track Bio Link Click](/docs/creator/bio-track-click): Append a click record + increment BioLink.clickCount. Two writes happen in parallel; a missing link silently no-ops the increment but still records the view. - [Get Bio Analytics](/docs/creator/bio-analytics): Owner-only analytics aggregate for a bio page over a configurable time window. Returns total/unique views, top referrers/devices/countries, and per-day view counts. - [Get DM Config](/docs/creator/dm-config): Read the creator's current DM type, price, and active flag. Owner-only. - [Update DM Config](/docs/creator/dm-config-update): Set DM type / price / active flag in one atomic call. Side effects sync DMPackage rows + flip manual social link visibility on DM ON↔OFF transitions. Public bio cache invalidated. - [Get Vacation Status](/docs/creator/vacation): Read the creator's vacation flag plus the optional start/end window. Owner-only. - [Set Vacation Mode](/docs/creator/vacation-update): Toggle vacation mode with optional start/end window. Status flips ACTIVE↔VACATION only — SUSPENDED/BANNED/DEACTIVATED accounts are protected from this transition. - [Get Payout Settings](/docs/creator/payout-settings): Consolidated read of bank details, Stripe Connect status, preferred method, and the available-methods bitmap. Owner-only. - [Update Bank Details](/docs/creator/bank-details): Sparse update of bank fields (IBAN/SWIFT/holder/country/name) plus optional preferred-method choice. ANY bank field change resets the verified flag — admin must re-verify before BANK_TRANSFER becomes available again. - [Start KYC Verification](/docs/creator/kyc-start): Initiate identity verification with the active KYC provider. Returns a redirect URL for the hosted verification flow. Vendor identity is admin-managed — clients receive an opaque provider id. - [Get KYC Status](/docs/creator/kyc-status): Read current KYC state plus the active provider id and completion timestamp. Owner-only. Provider value is opaque to clients. - [Initiate Stripe Connect](/docs/creator/stripe-connect-initiate): Create a Stripe Connect Express account and return a hosted onboarding URL. KYC must be APPROVED first. Idempotent — repeated calls return a fresh link for the same account. - [Get Stripe Connect Status](/docs/creator/stripe-connect-status): Real-time pull from the Stripe API with DB sync. Falls back to stored DB values when Stripe SDK is unavailable. Returns charges/payouts enabled flags + onboarding completion flag. - [Refresh Onboarding Link](/docs/creator/stripe-connect-refresh-link): Get a fresh hosted onboarding link for an existing Stripe Connect account. Use when the previous link expired or the user closed the tab without finishing. - [Get Dashboard Login Link](/docs/creator/stripe-connect-dashboard-link): One-shot login URL for the creator's Stripe Express dashboard. Requires the account to be ACTIVE. Use to deep-link into payouts, payment methods, and settings. - [Subscribe to Bio Page](/docs/creator/subscribe): Public fan-side email signup for a creator's bio page mailing list. Double-opt-in — confirmation email is sent through the active email provider (admin-managed) with a token. - [Confirm Subscription](/docs/creator/subscribe-confirm): Public token endpoint. The fan clicks the link in the confirmation email; this flips confirmed=true and clears the token. Single-use. - [Resend Confirmation Email](/docs/creator/subscribe-resend): Generate a fresh confirmation token and re-dispatch the email via the active email provider. Always returns the same safe message — no enumeration leak. - [Unsubscribe](/docs/creator/unsubscribe): Public soft-delete endpoint. Sets unsubscribedAt = now() — the row stays for audit but is excluded from active subscriber lists and future newsletter dispatches. - [List Subscribers (Creator)](/docs/creator/subscribers): Owner-only paginated list of confirmed, active mailing-list subscribers. Filter is confirmed=true AND unsubscribedAt=null. - Creator Analytics: Read-only dashboard endpoints for the authenticated creator's own bio page — overview, traffic, geo, devices, trend, sessions, link performance, CSV export. All queries scoped to the caller's bio page. - [Creator Analytics Overview](/docs/creator-analytics/overview): Top-line counters for the authenticated creator's bio page — total views, unique visitors (by hashed visitorId), total link clicks, CTR. Scoped to the caller's own bio page; foreign access is impossible. - [Creator Traffic Sources](/docs/creator-analytics/traffic): Top 15 referrer domains for the authenticated creator's bio page, with visit counts and percentage share. Direct visits show up as "direct". - [Creator Geo Distribution](/docs/creator-analytics/geo): Top 20 visitor countries for the authenticated creator's bio page. Country names from GeoIP at session-create; sessions with unknown country fall under "Unknown". - [Creator Device Breakdown](/docs/creator-analytics/devices): Visitor device-type breakdown for the authenticated creator's bio page (mobile / tablet / desktop / unknown). All segments returned, sorted by count descending. - [Creator Daily Trend](/docs/creator-analytics/trend): Per-day views and clicks for the creator's bio page. Bucketed via Postgres date_trunc('day', enteredAt). Days with no traffic are absent — fill gaps client-side. - [Creator Session Metrics](/docs/creator-analytics/sessions): Aggregate session metrics for the authenticated creator's bio page — total sessions, bounce rate, average session duration, average pages per session. - [Creator Link Performance](/docs/creator-analytics/links): Per-link click counts and CTR for the creator's bio page. Cross-DB join — clicks come from Analytics DB, link metadata (title + URL) is fetched from main DB by id. - [Export Creator Analytics (CSV)](/docs/creator-analytics/export): Download a CSV of the overview, traffic, or links endpoint. CSV-injection-safe via formula-character escaping. Returns text/csv with attachment Content-Disposition. - Discover: Public creator discovery — search, trending, featured, by category. Authenticated recently-viewed history. - [Search Creators](/docs/discover/search): Public creator search across username, displayName, and bio. PostgreSQL full-text search with ILIKE fallback. Cursor-based pagination, CDN-cached 5min/10min SWR. - [Get Trending Creators](/docs/discover/trending): Public trending creator list. Multi-factor scoring (7-day window) cached in Redis 15min. Falls back to totalMessages sort if scoring fails. CDN-cached 5min. - [Get Featured Creators](/docs/discover/featured): Public admin-curated featured creator list. Filtered by current time window (startsAt/endsAt) + creator active status. Ordered by admin-set position. CDN-cached 5min. - [Browse by Category / Platform](/docs/discover/category): Public creator browse by platform (Instagram / X / etc) AND optional content category. Three sort modes (recent / popular / rating). DM-type filter. Cursor pagination. - [Record Profile View](/docs/discover/history-record): Authenticated. Upserts a RecentlyViewed row for the (user, creator) pair — refreshes viewedAt on subsequent visits. Returns whether the row was recorded. - [Get Recently Viewed](/docs/discover/history-list): Authenticated. Returns the calling user's recently viewed creators ordered by viewedAt DESC. Active-creator filter — inactive / suspended / vacationing creators are dropped from the read. - [Clear Recently Viewed](/docs/discover/history-clear): Authenticated. Hard-deletes every RecentlyViewed row for the calling user. Returns the count actually deleted. No undo. - i18n: Public locale catalog + translation bundle delivery. Multi-layer cache (L1 process / L2 Redis / L3 CDN), ETag-aware, version-pinning for immutable cache. APPROVED-only output. - [List Locales](/docs/i18n/locales): Active language catalog plus a per-locale version map. Sanitized output — only code, name, nativeName, isRtl, isDefault. Use the version map to decide when to refetch translation bundles. - [Get Translation Bundle](/docs/i18n/bundle): Full APPROVED translation bundle for a locale. Flat map keyed by "namespace.key". ETag + If-None-Match for conditional GET, optional ?v=N for 1-year immutable cache. - [Get Namespace Bundle](/docs/i18n/namespace): Single-namespace translation bundle. Like the full bundle but scoped to one namespace and with non-prefixed keys. Same ETag + version-pinning semantics. - Legal: Public privacy policy and terms of service. Admin-managed content. - [Get Privacy Policy](/docs/legal/privacy): Public read of the platform privacy policy. Content is admin-managed via ConfigService. Returns the body plus the last-updated timestamp. - [Get Terms of Service](/docs/legal/terms): Public read of the platform terms of service. Content is admin-managed via ConfigService. Same shape as the privacy policy endpoint. - Messages: DM (direct message) inbox, search, conversations, unread badge, message detail, send/reply/reject/rate - [List Messages (Inbox)](/docs/message/list): Paginated inbox / sent view. Filter by role (fan = sent, creator = received) and optionally by chat session. Content is decrypted server-side per row. - [Search Messages](/docs/message/search): Case-insensitive substring search across messages where you're the sender or receiver. Filters on the searchContent column (decrypted, indexed for search). Decrypts content for the response. - [List Conversations](/docs/message/conversations): Paginated chat session list with the other party's profile slice, last message preview (encrypted placeholder), unread count per session, and bidirectional block flags. - [Get Unread Count](/docs/message/unread-count): Lightweight badge counter — total unread messages where you're the receiver. Counts messages in PENDING / ESCROWED / DELIVERED states across all sessions. - [Get Message Detail](/docs/message/detail): Read a single message by id with all client-facing fields. Ownership-checked — you must be the sender or receiver. Content decrypted on read. - [Send Message](/docs/message/send): Fan sends a DM to a creator. Validates verification, block, DM config, vacation, dmType match, duplicate window, paid-DM concurrency cap, balance, then creates message + escrow atomically. Quarantines on moderation flag (silent to caller). - [Reply to Message](/docs/message/reply): Creator-only reply. Requires ESCROWED or DELIVERED status. Atomically transitions REPLIED→COMPLETED + releases escrow (paid) or skips (free). Compensates on escrow-release failure. - [Reject Message](/docs/message/reject): Creator-only rejection. Requires ESCROWED or DELIVERED status. Triggers full refund to fan's wallet for paid DMs (atomic claim + escrow refund). Optional reason captured for audit + notification. - [Rate Message](/docs/message/rate): Fan rates a completed conversation 1–5 stars. Atomic create + recompute creator's avgRating / ratingCount in one transaction. Single-shot — duplicate attempts are 409 (P2002). - Notifications: In-app notification inbox, unread badge, mark-read, preferences, web push subscriptions, email unsubscribe - [List Notifications](/docs/notification/list): Paginated in-app notification feed for the calling user. Optional read-state filter. Returns the full row including event key, title, body, and free-form data payload. - [Unread Notification Count](/docs/notification/unread-count): Lightweight badge counter — total unread notifications for the calling user. Pairs with the inbox list endpoint for navigation badges. - [Mark Notification Read](/docs/notification/mark-read): Flip a single notification's read flag to true and stamp readAt. Ownership-checked. Idempotent — re-marking only refreshes the timestamp. - [Mark All Notifications Read](/docs/notification/read-all): Bulk-flip every unread notification for the calling user to read=true. Returns the count actually updated. Scoped to caller — no cross-user leak. - [Delete Notification](/docs/notification/delete): Hard-delete a single notification by id. Ownership-checked. There is no recycle bin or undo flow. - [Get Notification Preferences](/docs/notification/preferences): Per-event channel matrix (email / push / in-app / webPush / SMS) merged from system defaults plus user overrides. The customized flag tells the UI whether each row is user-modified. - [Update Notification Preference](/docs/notification/preferences-update): Save the user's per-channel override for a single event. Upserts a NotificationPreference row. eventKey must exist in the admin-managed defaults catalog. - [Clear Read Notifications](/docs/notification/clear-read): Bulk-delete every read notification for the calling user. Returns the count actually deleted. Unread rows are untouched. - [Email Unsubscribe (Public)](/docs/notification/unsubscribe): Public HMAC-token endpoint reachable from email footers without login. Adds the email to the suppression list AND disables the email channel in every event preference for the matching user. - [Subscribe to Web Push](/docs/notification/webpush-subscribe): Register a W3C PushSubscription with the server. Endpoint-keyed upsert handles browser key regeneration AND device handover (different user on the same browser → reassign). - [Unsubscribe Web Push](/docs/notification/webpush-unsubscribe): Soft-deactivate a single web push subscription by endpoint. Ownership-checked. Server keeps the row (active=false) for forensic / re-subscribe-detection. - [List Web Push Subscriptions](/docs/notification/webpush-subscriptions): Read the calling user's active web push subscriptions. Returns up to 100 rows ordered newest-first. Public-safe slice — keys NOT exposed. - Payment: Wallet load packages, balance, Stripe checkout sessions, transaction activity feed - [Get Load Packages](/docs/payment/wallet-packages): Public list of suggested wallet top-up amounts plus the absolute min/max limits and active currency. Drives the load-amount picker in the wallet UI. - [Get Wallet Balance](/docs/payment/wallet-balance): Read the calling user's FAN wallet balance and frozen flag. Returns 0.00 + frozen=false if no wallet row exists yet (no auto-create on read). - [Create Wallet Load Session](/docs/payment/wallet-load): Create a Stripe Checkout session for a wallet top-up. Validates min/max/balance-cap via admin config. Idempotency-Key header recommended for retry safety. Actual credit happens server-side via webhook. - [Get Wallet Activity](/docs/payment/wallet-activity): Paginated wallet transaction feed with optional type filter. Each row carries balance-before / balance-after for an audit-friendly trail. No wallet → empty page. - Payout: Creator-side payout endpoints — request a payout from your creator wallet, fetch your monthly payout history. Admin payout management lives under a separate scope. - [Request a Payout](/docs/payout/request): Creator requests a payout from their wallet via Stripe Connect or bank transfer. Long pre-condition gate (KYC, tax form, payout method readiness, balance, cooldown). Kill-switchable. Returns just the new payoutId. - [Get Payout Report](/docs/payout/report): Creator-scoped payout history. Optional month filter (YYYY-MM, validated). Returns up to 500 most-recent rows, total amount, and count. - Platform: Aggregate platform statistics — public, CDN-cached counters for trust badges and homepage. - [Get Platform Stats](/docs/platform/stats): Public aggregate counters — active creators, total messages, total earned. CDN- and Redis-cached for 1 hour. Render in trust badges, homepage hero, footer counters. - Presence: Last-seen + online status for any user. Read-side of the presence state written by chat-service via Socket.IO. - [Get Last-Seen + Online Status](/docs/presence/last-seen): REST read of socket-written presence state. Returns isOnline (live socket connection) and lastSeen (ISO-8601 of final disconnect, ~30-day TTL). Soft-degrades to "offline + null" when the session Redis is unreachable. - Referral: Personal referral link, click tracking, dashboard with rewards, coupon application - [Get Referral Link](/docs/referral/link): Get-or-create the calling user's personal referral link. First call generates a code from their username (or random UUID slice on collision); subsequent calls return the existing one. - [Track Referral Click](/docs/referral/click): Public endpoint. Increments the click counter on a ReferralLink. Silent on missing/inactive codes — the request never fails. - [Get Referral Dashboard](/docs/referral/dashboard): Authenticated. Returns the user's referral link snapshot (clicks, signups, conversions, totalEarnings) plus their last 50 active rewards (clawed-back rewards excluded). - [Apply Coupon](/docs/referral/coupon-apply): Authenticated. Validates a coupon code against expiry, applicability, min purchase, total / per-user usage caps under a SELECT FOR UPDATE row lock. Returns the calculated discount. - Support: User-facing support tickets — list, create, detail, reply, reopen. Owner-scoped reads, throttled creates, status state machine. Admin endpoints documented separately. - [List My Tickets](/docs/support/list): Owner-scoped paginated list of the current user's support tickets. Filter by status. Always returns YOUR tickets — no admin lens, no cross-user reads possible. - [Create Support Ticket](/docs/support/create): Open a new ticket as the current user. Returns just the new ticketId. Throttled to 5 per minute per IP. Optional category drives default priority. Sends a ticket_created notification fire-and-forget. - [Get Ticket Detail](/docs/support/detail): Single ticket including its full message history and category. Owner-scoped — querying someone else's ticket returns 404 (not 403) so existence is never leaked. - [Reply to Ticket](/docs/support/reply): Add a user reply to your ticket. Auto-transitions WAITING_USER → IN_PROGRESS. Rejects when the ticket is CLOSED. Sends a ticket_update notification to the assigned agent (if any). - [Reopen Ticket](/docs/support/reopen): Move a RESOLVED or CLOSED ticket back to OPEN. Clears resolvedAt + closedAt. Owner-only. Fails if the ticket is in any other status. - Themes: Public theme preset catalog (CLIENT or ADMIN target). Active preset selector for live theming. - [List Theme Presets](/docs/theme/list): Public list of PUBLISHED theme presets for the creator bio editor / client-web theming. Sanitized output — only id/name/slug + light/dark/typography tokens. - [Get Active Theme](/docs/theme/active): Public read of the platform's currently active client-web theme preset. Includes layout + assets (full theming surface). MUST pass ?target=CLIENT — default differs. - Upload: Pre-signed direct-to-storage upload URLs (avatar / media / document). Admin-managed allowlists. - [Get Presigned Upload URL](/docs/upload/presign): Two-step upload flow — server returns a signed PUT URL; client uploads file bytes directly to object storage. Three types (avatar / media / document) with admin-managed MIME and size allowlists. - User: Profile, avatar, intent, username, settings, account lifecycle, consent, blocking - [Get User Profile](/docs/user/profile): Read the calling user's full profile — identity fields + flags (twoFactorEnabled, isCreator, emailVerified) + linked OAuth accounts + attribution data. - [Update User Profile](/docs/user/profile-update): Patch displayName, bio, or avatarUrl. Only fields present in the body are updated. Returns the fresh updated profile slice. - [Set Avatar](/docs/user/avatar-set): Persist a new avatar URL on the user row and clean up the previous file from object storage in the background. - [Remove Avatar](/docs/user/avatar-remove): Clear the user's avatarUrl and delete the file from object storage in the background. - [Set User Intent](/docs/user/intent): One-time, post-registration choice — FAN or CREATOR. Drives the post-signup landing destination and is rejected on second call. - [Change Username](/docs/user/username): Set or rotate the user's username with availability + reserved checks, a per-user cooldown, and a history record. First-time set has no cooldown. - [Check Username Availability](/docs/user/check-username): Real-time availability probe for the registration / settings form. Public — no auth required. Returns false on bad format too, so the UI can stop after one round-trip. - [Change Email (Request)](/docs/user/change-email): Start an email-change flow by re-confirming the password and sending a verification link to the NEW email. Account email only flips after the new address is verified. - [Get User Settings](/docs/user/settings): Read the user's preferences row — locale, theme, three notification toggles, digest mode. Lazily creates the default row on first access. - [Update User Settings](/docs/user/settings-update): Sparse update of preferences (locale, theme, notification flags, digest mode). Locale changes also sync to the legacy User.locale field. - [Deactivate Account](/docs/user/deactivate): Temporarily deactivate the current account. Profile becomes hidden, all sessions revoked. Reversible via /users/reactivate. - [Reactivate Account](/docs/user/reactivate): Bring a DEACTIVATED account back to ACTIVE. Two auth modes — bearer JWT (logged-in user) OR opaque token from email link (no JWT required). Cancels any pending deletion in the same transaction. - [Request Data Export (GDPR)](/docs/user/gdpr-export): Right-of-Access (Art. 15) — queue an export of the user's data. Returns a request id that the client polls until COMPLETED, then downloads via the signed-URL endpoint. - [Get Export Status](/docs/user/gdpr-export-status): Poll the status of a previously created GDPR export request. Returns the current state plus completedAt when finished. - [Download Export](/docs/user/gdpr-export-download): Once status is COMPLETED, fetch a time-limited signed URL for the export archive. The URL is short-lived — render it into an `` and trigger immediately. - [Request Export (Legacy)](/docs/user/export-legacy): Older /users/export alias. Same intent as POST /gdpr/export but with a simpler response shape and a slightly looser duplicate-check. Prefer the GDPR endpoint for new clients. - [Request Account Deletion (GDPR)](/docs/user/gdpr-delete): Right-to-Erasure (Art. 17) — schedule the account for deletion after a grace period. Account is deactivated immediately and all sessions revoked. - [Cancel Pending Deletion](/docs/user/gdpr-delete-cancel): Stop a previously scheduled GDPR deletion before the grace period ends. Reactivates the account in the same transaction. Sessions stay revoked — re-login required. - [Request Deletion (Legacy)](/docs/user/delete-legacy): Older /users/delete endpoint — same effect as POST /gdpr/delete but additionally requires the current account password and returns only the scheduled date. - [Record Consent](/docs/user/consent-record): Append-only log of user consent decisions (TOS, privacy, cookies, etc). Captures IP and user-agent for compliance audit. - [Get Consent History](/docs/user/consent-history): List the user's last 100 consent decisions in reverse-chronological order. Useful for "your consent history" UIs and compliance exports. - [Block a User](/docs/user/block): Add a target user to the caller's block list. Self-block is rejected; double-block is a 409. Audit-logged for moderation review. - [Unblock a User](/docs/user/unblock): Remove a previously blocked user from the caller's block list. Returns 404 if no block row exists for this pair. - [List Blocked Users](/docs/user/blocked): Read the caller's block list. Returns up to 50 most recently blocked users plus the total count. Pagination is not exposed by the controller (fixed at page 1, limit 50). - [Submit Appeal](/docs/user/appeals): File an appeal against a moderation action (ban, fraud flag, content removal, report action). Reachable by banned users via BypassBanCheck. One pending appeal per user at a time. - [Get Attribution](/docs/user/attribution): Read the immutable registration attribution snapshot — UTM params, first referrer, landing page, device, country, referral chain. Captured once at signup and never changes.