All REST API endpoints and usage
API Reference
All API routes live under src/app/api/. They are Next.js App Router route handlers using the standard GET, POST, etc. export convention.
Authentication
Frame.io OAuth
GET /api/auth/frameio
Initiates the Frame.io OAuth flow by redirecting to Adobe IMS with the configured client ID and scopes.
GET /api/auth/frameio/callback
Handles the OAuth callback. Exchanges the authorization code for access/refresh tokens and stores them in HTTP-only cookies.
Video Processing & Storage
POST /api/clips/store
Fetches a processed clip from the Modal API (with retry logic), uploads the video to Supabase Storage (session-videos bucket), and saves the stats JSON to the clip record. Requires authentication -- verifies the caller owns the clip via coach_id.
Body:
{
"clipId": "uuid"
}
POST /api/sessions/store
Similar to clip store but operates at the session level. Fetches the processed session video from Modal, uploads to Supabase Storage, and saves stats. Requires authentication -- verifies the caller owns the session via coach_id.
Body:
{
"sessionId": "uuid"
}
GET /api/video/sign
Generates an HMAC-signed stream URL for a given upstream video URL. Requires authentication. The signed URL has a 1-hour TTL.
Query params:
| Param | Description |
|---|---|
url | The upstream video URL to sign for streaming |
Response: { "url": "/api/video/stream?url=...&expires=...&token=..." }
GET /api/video/stream
Video stream proxy with byte-range support. Proxies video from allowlisted hosts (Modal, Supabase, Frame.io) to the client. Handles Range headers for seeking. Requires a valid HMAC token (obtained from /api/video/sign).
Query params:
| Param | Description |
|---|---|
url | The source video URL to proxy |
token | HMAC signature (from /api/video/sign) |
expires | Token expiry timestamp in ms |
Frame.io Integration
All Frame.io endpoints require a valid OAuth token stored in the frameio_token cookie. Returns 401 if the token is missing or expired.
GET /api/frameio/me
Returns the current Frame.io user profile.
GET /api/frameio/projects
Lists workspaces or projects for an account.
Query params:
| Param | Description |
|---|---|
accountId | The Frame.io account ID |
GET /api/frameio/assets
Lists children (files and folders) of a given folder.
Query params:
| Param | Description |
|---|---|
folderId | The Frame.io folder/asset ID |
POST /api/frameio/import
Imports files from Frame.io into Surflink. Downloads assets, creates a session with clips, and sends each clip to Modal for AI analysis.
Body:
{
"assets": [{ "id": "asset-id", "name": "clip.mp4" }],
"sessionTitle": "Morning Session"
}
Limits: Max 10 clips per import, 5-minute timeout.
Surf Conditions
GET /api/surf/forecast
Returns surf conditions for all Barbados spots.
Query params:
| Param | Description |
|---|---|
detail | If true, fetches individual spot data (slower, more detailed) |
coast | Filter by coast (e.g., west, south) |
minWave | Minimum wave height filter (feet) |
GET /api/surf/spot/[slug]
Returns detailed forecast for a single surf spot.
Query params:
| Param | Description |
|---|---|
days | Number of forecast days (1-6, default 1) |
Response includes: wave height/period/direction, wind speed/direction/gusts, surf rating, tide data.
Achievements
POST /api/achievements/check
Evaluates 20+ achievement rules for a student and awards any newly earned badges.
Body:
{
"studentId": "uuid"
}
POST /api/achievements/seed
Seeds the achievements table with all achievement definitions. Idempotent -- safe to call multiple times.
Notifications
POST /api/notifications/send
Creates a notification record in the database and optionally sends:
- APNs push to registered iOS/watchOS devices
- Email via Resend for critical notification types (lesson reminders, achievements)
Body:
{
"userId": "uuid",
"type": "lesson_reminder",
"title": "Lesson Tomorrow",
"body": "You have a lesson scheduled for 9am at Freights."
}
Invitations
POST /api/invite
Generates an invite token for a student and optionally sends an email invitation via Resend.
Body:
{
"studentId": "uuid",
"coachId": "uuid"
}
Returns the invite URL that the student can use to accept and create their account.
POST /api/invite/parent
Generates a parent invite token and optionally sends an email. Tokens are stored in the parent_invite_tokens table with a 7-day expiry.
Body:
{
"studentId": "uuid",
"coachId": "uuid",
"parentEmail": "parent@email.com",
"parentName": "Jane Doe"
}
Billing (Stripe)
POST /api/stripe/checkout
Creates a Stripe Checkout Session for a coaching package. Automatically creates a Stripe Product and Price if the package doesn't have one yet. Requires authentication.
Body:
{
"packageId": "uuid",
"studentId": "uuid"
}
Response: { "url": "https://checkout.stripe.com/..." }
POST /api/stripe/portal
Creates a Stripe Customer Portal session for managing an existing subscription. Requires authentication.
Body:
{
"subscriptionId": "sub_..."
}
Response: { "url": "https://billing.stripe.com/..." }
POST /api/stripe/webhook
Stripe webhook endpoint. Verifies the webhook signature and processes events:
checkout.session.completed-- Creates subscription and payment recordscustomer.subscription.updated-- Updates subscription status and billing periodcustomer.subscription.deleted-- Marks subscription as cancelledinvoice.payment_failed-- Marks subscription as past due
Note: This endpoint must be configured in the Stripe Dashboard under Webhooks with the events listed above.