Stripe, Frame.io, Surfline, Resend, and APNs
Integrations
Surflink integrates with several external services. All are configured through environment variables.
Stripe (payments)
There are two distinct Stripe flows, discriminated in the webhook by a metadata.kind of platform or marketplace:
Platform subscriptions (org pays Surflink)
- Plans, base prices, and per-seat prices live in
src/lib/stripe.js, with Price IDs from env. POST /api/billing/subscribebuilds line items (base + seats) and opens a subscription Checkout session withmetadata.kind: 'platform'.POST /api/billing/portalopens the Customer Portal using the org's stored customer id (no client-supplied id, so no IDOR).- The webhook keeps
org_subscriptionsin sync.
Marketplace (student pays coach)
POST /api/stripe/checkoutlazily creates a Product+Price from a coaching package and opens checkout (subscriptionif the package has a duration, elsepayment) withmetadata.kind: 'marketplace'.POST /api/stripe/portalopens the portal for a student subscription found via RLS.- The webhook writes
subscriptionsandpaymentsrows.
Config
| Variable | Purpose |
|---|---|
STRIPE_SECRET_KEY | Secret key |
STRIPE_WEBHOOK_SECRET | Webhook signature verification |
Configure the webhook endpoint (/api/stripe/webhook) in the Stripe dashboard.
Frame.io (video assets)
Adobe Frame.io V4 via Adobe IMS OAuth (src/lib/frameio.js). Coaches connect from the Upload page, browse workspaces/projects/folders, and import up to 10 video assets per batch. Tokens are stored in HTTP-only cookies.
Surfline (surf conditions)
src/lib/surfline.js wraps the Surfline KBYG API (imperial units, 10-minute in-memory cache). When Surfline is unavailable, src/lib/conditions.js falls back to the Open-Meteo Marine API. Surfaced in the dashboard, training session scheduling, and journal. The default spot catalog targets Barbados/BSA spots.
Resend (email) -- optional
Transactional email for invites and critical notifications. Every send is guarded by RESEND_API_KEY, so email is optional -- without it, invite links are surfaced in the UI to copy manually.
Apple Push Notifications (APNs) -- optional
/api/notifications/send signs an APNs JWT (via jose) and delivers to devices registered in push_tokens. Requires the APNS_* variables and an internal service-role authorization header.