DocHub
submit-custom-course edge function that orchestrates the entire custom course flow

Edge Function: submit-custom-course

A single Supabase edge function on the main HypnoELP project that handles all custom course operations — authentication, input validation, and orchestration of the n8n pipeline.

Purpose

Act as the API gateway between the frontend form and the backend n8n workflows. Handles token verification, request validation, and routes requests to the appropriate n8n webhook based on the step field.

Architecture

Deployed on main HypnoELP Supabase (kagtryxgjwavupzlmlzv).

POST https://kagtryxgjwavupzlmlzv.supabase.co/functions/v1/submit-custom-course

All requests include a step field that determines the action:

Step Action n8n Webhook
health_check Validate user inputs /webhook/api/v1/custom-course-health-check
generate_scripts Generate 3 personalized scripts /webhook/api/v1/custom-script
generate_audio Convert script to audio /webhook/api/v1/custom-audio
support_request Send support email via Resend (direct, no n8n)

Authentication

The function supports two token types:

JWT Token (from app)

  • Issued by the HypnoELP app after an in-app purchase
  • Starts with eyJ (base64 JSON header)
  • Verified using JWT_SECRET_SUPABASE environment variable
  • Contains user_id in payload
  • Stored in custom_course_purchases.link_token
  • Issued for regeneration requests (when user needs to redo their course)
  • Expires after 24 hours (checked against updated_at)
  • Must have status = 'active' and is_submitted = false
  • Marked as submitted after audio generation begins

Test Mode

A testMode: true flag or dev-test-token-12345 token bypasses authentication for development.

Request Validation

generate_scripts

  • issue: string, 20-500 chars
  • goal: string, 20-500 chars
  • feel: string, 10-500 chars
  • why: string, 10-500 chars
  • title: string, 5-55 chars
  • scripts: array of exactly 3 objects with number (1-3) and technique (valid technique code)

generate_audio

  • script: string (full script text)
  • voice: "male" or "female"
  • title: string

health_check

  • issue: string, min 10 chars
  • goal: string, min 10 chars
  • feel: string (optional)
  • why: string (optional)

Script Safety Check

After generate_scripts, the edge function checks for a safety object in the n8n response. If any script fails the safety check (all_safe === false), the entire request is rejected with error code script_safety_failed.

Purchase Tracking

On generate_audio, the function immediately marks the purchase token as submitted (is_submitted = true) to prevent duplicate submissions across devices. This happens before calling the audio workflow.

API Endpoints (Internal n8n Webhooks)

Webhook Purpose
worker1.ipnoelp.com/webhook/api/v1/custom-course-health-check Input validation
worker1.ipnoelp.com/webhook/api/v1/custom-script Script generation
worker1.ipnoelp.com/webhook/api/v1/custom-audio Audio generation

Variables

Variable Source Purpose
SUPABASE_URL Environment Supabase project URL
SUPABASE_SERVICE_ROLE_KEY Environment Admin DB access
JWT_SECRET_SUPABASE Environment JWT verification secret
RESEND_API_KEY Environment Email sending for support requests

Data Model

The function reads/writes to the custom_course_purchases table:

Column Usage
link_token UUID token lookup
purchase_token JWT token lookup
status Must be active for valid tokens
is_submitted Set to true after audio generation starts
updated_at Used for 24-hour UUID token expiration

Handshakes

From To Protocol
Form frontend Edge function HTTPS POST with JSON
Edge function n8n webhooks HTTP POST (internal)
Edge function Supabase DB Service role client
Edge function Resend API HTTPS (support emails)

Dependencies

  • Supabase (hosting, DB access, auth verification)
  • n8n worker-1 (backend processing)
  • Resend (support email delivery)
  • jose library (JWT verification)

Deployment

supabase functions deploy submit-custom-course --project-ref kagtryxgjwavupzlmlzv

Status

Production. Deployed on main HypnoELP Supabase. Handles all custom course operations.