# unLocked CRM — API Reference

> Generated from a full scan of the codebase on 2026-08-23.
> Machine-readable version: [`public/openapi.json`](./public/openapi.json) (OpenAPI 3.1) — also served live at `GET https://gzigyepfasiumngxilai.supabase.co/functions/v1/openapi-spec`.

## Supported API And AI Connection Actions — October 2026

The unLocked API powers the secure AI connection. Claude, ChatGPT, Grok, Grok Bots, Muse AI, ChatGPT dots, Claude Code, and Cursor inherit the same supported contact, messaging, quote, underwriting, and link actions within approved permissions and plan access. Agents can review daily priorities, pull a full contact profile, manage duplicates and documents, send and schedule texts and emails, run live quotes, save and file quotes, send branded PDF quotes now or scheduled with saved wording and a chosen mailbox, list quote opens, and retrieve or send booking, intake, Medicare quote, and life quote links. unLocked remains the system of record; customer data is never used to train AI. Pro and Max. Starting an application from a quote is coming soon; annuity quoting is not included.

Full catalog: https://unlockedcrm.ai/api#supported-actions

## Base URL

```
https://gzigyepfasiumngxilai.supabase.co/functions/v1
```

Every endpoint is a serverless edge function under this origin. The app itself is served from `https://app.unlockedcrm.ai` (plus white-label domains), but **all API calls go to the functions origin above**.

## Authentication (plain English)

There are four ways an endpoint can be protected:

| Scheme | How a client authenticates | Used by |
|---|---|---|
| **API key** | Send `x-api-key: sk_live_...` header. Keys are created in **Settings → API**, carry scoped per-resource permissions (read/create/update/delete), support IP allowlisting, and are rate-limited to **100 requests/minute**. | The Public API (`/public-api`) |
| **User JWT** | Sign in to the app (email/password, Google, etc.), take the session access token, and send `Authorization: Bearer <token>`. The function validates the user and applies their role/workspace scoping. | All app-facing internal functions |
| **Tool secret** | Server-to-server calls from the AI voice platform send a shared secret in the `X-Tool-Secret` header. Not usable by end users. | AI agent tool webhooks (book/cancel/reschedule appointment, mark DNC, …) |
| **Webhook signature** | The calling provider (Stripe, Twilio, Meta, HealthSherpa, Calendly, …) signs the request; the function verifies the signature or a per-endpoint secret. | Inbound webhook receivers |

Anonymous/public endpoints: `GET /openapi-spec`, `GET /public-api?resource=health`, plus public-facing form/booking/quote submit endpoints which are unauthenticated by design (they create leads/appointments for prospects).

### Scoped permissions (machine-readable)

OAuth 2.0 (authorization code + PKCE) and API keys use the **same named scopes**. Request the least-privilege set.

- Authorization server metadata: `https://unlockedcrm.ai/.well-known/oauth-authorization-server`
- Protected-resource metadata (RFC 9728): `https://unlockedcrm.ai/.well-known/oauth-protected-resource`
- OpenAPI security schemes: `OAuth2` (with `flows.authorizationCode.scopes`) and `ApiKeyAuth` (with `x-scopes`) in `https://unlockedcrm.ai/openapi.json`

| Scope | Grants |
|---|---|
| `read:contacts` / `write:contacts` | Read / create + update contact records |
| `read:leads` / `write:leads` | Read / create + update leads and pipeline records |
| `read:policies` / `write:policies` | Read / create + update policies, renewals, lapse status |
| `read:quotes` / `write:quotes` | Read / create + update quotes and comparisons |
| `read:commissions` / `write:commissions` | Read / write commission statements and reconciliation data |
| `read:tasks` / `write:tasks` | Read / create + update tasks and reminders |
| `read:appointments` / `write:appointments` | Read / create + update calendar appointments |
| `read:activities` / `write:activities` | Read / write activity and timeline history |
| `read:communications` / `write:communications` | Read call, SMS, email history / send messages and place calls |
| `read:agent_ai` / `write:agent_ai` | Read AI agent config and runs / trigger runs and update config |

Authorization endpoint: `https://mcp.unlockedcrm.ai/oauth?action=authorize` — Token endpoint: `https://mcp.unlockedcrm.ai/oauth?action=token` — Revocation: `https://mcp.unlockedcrm.ai/oauth?action=revoke`


## Error responses (JSON, always)

Every non-2xx response from the API is `application/json`. The API never returns HTML error pages to API clients. Machine-readable catalog: `https://unlockedcrm.ai/api/errors.json` and the `x-error-format` block plus `components.schemas.Error` in `https://unlockedcrm.ai/openapi.json`.

Envelope:

```json
{
  "error": {
    "code": "permission_denied",
    "message": "Permission denied for this resource or action.",
    "status": 403,
    "retryable": false,
    "resolution": "Request the scope named in error.required_scope and retry.",
    "required_scope": "write:leads",
    "request_id": "req_01J9ZC7Q2X5T",
    "docs_url": "https://unlockedcrm.ai/api#errors"
  }
}
```

| `error.code` | HTTP | Meaning | Retryable | How to resolve |
|---|---|---|---|---|
| `invalid_request` | 400 | Malformed request, missing parameter, or unknown `resource`. | No | Fix the `resource` query parameter or required body fields, then retry. |
| `unauthenticated` | 401 | Missing, malformed, or expired credentials. | No | Send a valid `x-api-key` header or `Authorization: Bearer <jwt>`. |
| `permission_denied` | 403 | Credentials lack the required scope. | No | Request the scope in `error.required_scope`, then retry. |
| `not_found` | 404 | Record or endpoint does not exist in this workspace. | No | Verify the `id`; do not retry the same request. |
| `conflict` | 409 | Duplicate key or concurrent update. | Once | Re-fetch the record, merge, retry once. |
| `validation_failed` | 422 | Field values failed validation. | No | Read `error.details[]` and correct the named fields. |
| `rate_limited` | 429 | Over 100 requests/minute for this key. | Yes | Wait `Retry-After` (or `error.retry_after_seconds`), then back off. |
| `internal_error` | 500 | Unexpected server error. | Yes | Retry with exponential backoff; quote `error.request_id` to support. |
| `upstream_error` | 502 | Downstream carrier or provider API failed. | Yes | Retry with exponential backoff. |

Agent guidance: branch on `error.code` (stable), not on `error.message` (human-readable, may change). Honor `error.retryable` and never retry a terminal code with the same payload.

## Public API (stable, external-facing)

Single endpoint, four methods. The `resource` query parameter selects the collection; the HTTP method selects the operation.

| Method | Path | Query params | Body | Description |
|---|---|---|---|---|
| GET | `/public-api` | `resource` (required), `id`, `limit` (max 100, default 50), `offset`, `sort` (`field:dir`), `fields`, `search`, `status` | — | List a collection, or fetch one record by `id`. |
| POST | `/public-api` | `resource` (required), `action=bulk` | Record object, or `{mode, records[]}` for bulk (max 1,000) | Create one record, or bulk-create. |
| PUT | `/public-api` | `resource`, `id` (both required) | Record fields to update | Update a record. |
| DELETE | `/public-api` | `resource`, `id` (both required) | — | Delete a record. |

**Resources:** leads, clients, activities, tasks, policies, appointments, communications, webhooks, pipelines, pipeline_stages, opportunities, workflows, email_campaigns, commissions, aca_leads, agent_ai_call_logs, agent_ai_scripts, agent_ai_campaigns, quotes, tags, call_recordings, call_disposition_logs, agent_presence, inbound_campaigns, inbound_vendors — plus meta resources `health` (no auth) and `whoami`.

**Lead field aliases** (auto-rewritten on write): `income`→`household_income`, `annual_income`→`household_income`, `dob`→`date_of_birth`, `zipcode`/`postal_code`→`zip_code`, `phone_number`/`mobile`→`phone`, `company`→`employer`, `job_title`→`occupation`. Unknown keys are matched against workspace custom fields (case-insensitive: `variable_name` → `field_key` → `name`).

**Outbound webhooks you can subscribe to** via `resource=webhooks`: lead.created, lead.updated, lead.deleted, lead.status_changed, client.created, client.updated, task.created, task.completed, policy.created, policy.renewed, appointment.created, appointment.cancelled, activity.created, opportunity.created, opportunity.updated, opportunity.stage_changed, workflow.activated, workflow.deactivated, email_campaign.sent, email_campaign.completed, commission.created, commission.updated, sms.sent, sms.received, sms.delivered, sms.failed, quote.saved.

### Sample: create a lead

```bash
curl -X POST 'https://gzigyepfasiumngxilai.supabase.co/functions/v1/public-api?resource=leads' \
  -H 'x-api-key: sk_live_xxxxxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com",
    "phone": "+15551234567",
    "source": "Website",
    "income": "85000",
    "custom_fields": { "preferred_contact_time": "Evenings" }
  }'
```

**Response `200 OK`:**

```json
{
  "data": {
    "id": "7f3a9c2e-…",
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com",
    "phone": "+15551234567",
    "household_income": "85000",
    "source": "Website",
    "status": "new",
    "created_at": "2026-08-23T20:00:00.000Z"
  },
  "matched_custom_fields": ["preferred_contact_time"],
  "unknown_fields": []
}
```

## Internal edge functions (full catalog)

These power the app UI, AI, telephony, quoting, and integrations. They accept JSON bodies; request shapes are function-specific and **not** covered by the public API stability guarantee. All support `OPTIONS` preflight. `cron` = also invoked on a schedule by pg_cron.


### AI & Agents (93)

| Function | Path | Methods | Auth | Cron | Description |
|---|---|---|---|---|---|
| `agent-activity-summary` | `…/functions/v1/agent-activity-summary` | POST | User JWT (Bearer) |  | Resolve caller's role from database — never trust client input |
| `agent-ai-call` | `…/functions/v1/agent-ai-call` | POST | User JWT (Bearer) |  | Call-source attribution, forwarded verbatim to the EL-native path via the `...body` spread below and written to agent_ai_call_logs there. Declared |
| `agent-ai-call-control` | `…/functions/v1/agent-ai-call-control` | POST | User JWT (Bearer) |  | Handle CORS preflight requests |
| `agent-ai-call-handler` | `…/functions/v1/agent-ai-call-handler` | POST | User JWT (Bearer) |  | Global map for tracking call-specific state |
| `agent-ai-call-listen` | `…/functions/v1/agent-ai-call-listen` | POST | User JWT (Bearer) |  | agent-ai-call-listen Browser-facing WebSocket endpoint that lets agency users live-listen to an |
| `agent-ai-call-resume` | `…/functions/v1/agent-ai-call-resume` | POST | User JWT (Bearer) |  | TwiML Resume Endpoint When the agent-ai-call-handler edge function hits its wall-clock timeout, |
| `agent-ai-call-status` | `…/functions/v1/agent-ai-call-status` | POST | Provider webhook signature |  | Note: This is a Twilio webhook that returns TwiML - CORS headers are not needed Twilio webhooks use POST only and don't go through browser CORS checks |
| `agent-ai-campaign-processor` | `…/functions/v1/agent-ai-campaign-processor` | POST | User JWT (Bearer) | ✓ | PROCESSOR BUDGET `BATCH_SIZE` was removed: per-tick per-campaign concurrency is now bounded |
| `agent-ai-campaign-status` | `…/functions/v1/agent-ai-campaign-status` | POST | User JWT (Bearer) |  | agent-ai-campaign-status Phase 2.5 §4.5 B3 — derived runtime state for the campaign list / detail UI. |
| `agent-ai-campaign-summary` | `…/functions/v1/agent-ai-campaign-summary` | POST | User JWT (Bearer) |  | Agent Ai Campaign Summary function. |
| `agent-ai-clone-voice` | `…/functions/v1/agent-ai-clone-voice` | POST | User JWT (Bearer) |  | Returns null if the caller is allowed to create another voice clone, or a Response describing why they aren't. Enforces "Max plans get unlimited |
| `agent-ai-elevenlabs-backfill-recordings` | `…/functions/v1/agent-ai-elevenlabs-backfill-recordings` | POST | User JWT (Bearer) |  | agent-ai-elevenlabs-backfill-recordings One-time (idempotent, re-runnable) backfill: walks every historical |
| `agent-ai-elevenlabs-book-appointment` | `…/functions/v1/agent-ai-elevenlabs-book-appointment` | POST | Tool secret (`X-Tool-Secret`) |  | agent-ai-elevenlabs-book-appointment EL server tool: creates an appointment after the caller confirmed a |
| `agent-ai-elevenlabs-cancel-appointment` | `…/functions/v1/agent-ai-elevenlabs-cancel-appointment` | POST | Tool secret (`X-Tool-Secret`) |  | agent-ai-elevenlabs-cancel-appointment EL server tool: cancels an existing scheduled appointment for the |
| `agent-ai-elevenlabs-find-slots` | `…/functions/v1/agent-ai-elevenlabs-find-slots` | POST | Tool secret (`X-Tool-Secret`) |  | agent-ai-elevenlabs-find-slots EL server tool: returns available appointment slots for the contact's |
| `agent-ai-elevenlabs-import-phone` | `…/functions/v1/agent-ai-elevenlabs-import-phone` | POST | User JWT (Bearer) |  | agent-ai-elevenlabs-import-phone Stage 2 of the EL-native pilot productionization. Imports a CRM-managed |
| `agent-ai-elevenlabs-inbound-personalization` | `…/functions/v1/agent-ai-elevenlabs-inbound-personalization` | POST | User JWT (Bearer) |  | agent-ai-elevenlabs-inbound-personalization Fired by ElevenLabs before its inbound agent answers the call. We respond |
| `agent-ai-elevenlabs-mark-dnc` | `…/functions/v1/agent-ai-elevenlabs-mark-dnc` | POST | Tool secret (`X-Tool-Secret`) |  | agent-ai-elevenlabs-mark-dnc EL server tool: adds the caller's number to the subaccount's DNC list |
| `agent-ai-elevenlabs-outbound-call` | `…/functions/v1/agent-ai-elevenlabs-outbound-call` | POST | User JWT (Bearer) |  | agent-ai-elevenlabs-outbound-call EL-native replacement for the legacy `agent-ai-call` outbound path. Lifts |
| `agent-ai-elevenlabs-pilot-check` | `…/functions/v1/agent-ai-elevenlabs-pilot-check` | POST | User JWT (Bearer) |  | agent-ai-elevenlabs-pilot-check Returns { pilot: boolean } for the requested subaccount. Used by the |
| `agent-ai-elevenlabs-reconcile-stuck` | `…/functions/v1/agent-ai-elevenlabs-reconcile-stuck` | POST | User JWT (Bearer) | ✓ | agent-ai-elevenlabs-reconcile-stuck The single authority for resolving non-terminal ElevenLabs-native call_logs. |
| `agent-ai-elevenlabs-remove-inbound-phone` | `…/functions/v1/agent-ai-elevenlabs-remove-inbound-phone` | POST | User JWT (Bearer) |  | agent-ai-elevenlabs-remove-inbound-phone The inverse of `agent-ai-elevenlabs-import-phone` with direction='inbound': |
| `agent-ai-elevenlabs-remove-phone` | `…/functions/v1/agent-ai-elevenlabs-remove-phone` | POST | User JWT (Bearer) |  | agent-ai-elevenlabs-remove-phone Phase 2 multi-outbound: remove a CRM phone number's ElevenLabs binding. |
| `agent-ai-elevenlabs-repair-sms-webhooks` | `…/functions/v1/agent-ai-elevenlabs-repair-sms-webhooks` | POST | Provider webhook signature |  | agent-ai-elevenlabs-repair-sms-webhooks One-off, operator-triggered repair for phone numbers whose Twilio SMS |
| `agent-ai-elevenlabs-reschedule-appointment` | `…/functions/v1/agent-ai-elevenlabs-reschedule-appointment` | POST | Tool secret (`X-Tool-Secret`) |  | agent-ai-elevenlabs-reschedule-appointment EL server tool: moves an existing scheduled appointment to a new slot. |
| `agent-ai-elevenlabs-transcript-proxy` | `…/functions/v1/agent-ai-elevenlabs-transcript-proxy` | POST | User JWT (Bearer) |  | agent-ai-elevenlabs-transcript-proxy Server-side proxy used by `LiveCallListenerDock`'s EL-native branch. |
| `agent-ai-elevenlabs-transfer` | `…/functions/v1/agent-ai-elevenlabs-transfer` | POST | Tool secret (`X-Tool-Secret`) |  | agent-ai-elevenlabs-transfer EL server tool: bridges the live Twilio call leg to a human number. |
| `agent-ai-elevenlabs-update-call-outcome` | `…/functions/v1/agent-ai-elevenlabs-update-call-outcome` | POST | Tool secret (`X-Tool-Secret`) |  | agent-ai-elevenlabs-update-call-outcome EL server tool: updates the call's outcome mid-call (e.g. when the agent |
| `agent-ai-elevenlabs-webhook` | `…/functions/v1/agent-ai-elevenlabs-webhook` | POST | Provider webhook signature |  | agent-ai-elevenlabs-webhook Ingests ElevenLabs post-call events and persists them into CRM. Single |
| `agent-ai-inbound-call` | `…/functions/v1/agent-ai-inbound-call` | POST | Provider webhook signature |  | Note: This is a Twilio webhook that returns TwiML - CORS headers are not needed Twilio webhooks use POST only and don't go through browser CORS checks |
| `agent-ai-realtime-token` | `…/functions/v1/agent-ai-realtime-token` | POST | User JWT (Bearer) |  | Handle CORS preflight requests |
| `agent-ai-reconcile-call` | `…/functions/v1/agent-ai-reconcile-call` | POST | User JWT (Bearer) |  | Reconciles an agent_ai_call_logs row against Twilio's actual call status. Used when status callbacks are missed/dropped, so we don't blindly mark |
| `agent-ai-script-generator` | `…/functions/v1/agent-ai-script-generator` | POST | User JWT (Bearer) |  | Generates or updates an Agent AI call script using Lovable AI. Returns structured JSON via tool-calling: name, openingScript, primaryScript, voicemailScript, bookingRules, objections[]. |
| `agent-ai-test-tools` | `…/functions/v1/agent-ai-test-tools` | POST | User JWT (Bearer) |  | Agent AI Test Tools — executes tool calls from the in-browser Test Sandbox. Modes: |
| `agent-ai-transfer-fallback` | `…/functions/v1/agent-ai-transfer-fallback` | POST | Provider webhook signature |  | Transfer Fallback Handler — Multi-Agent Cascade Called by Twilio when a <Dial> attempt completes (via the action= attribute). |
| `agent-ai-transfer-whisper` | `…/functions/v1/agent-ai-transfer-whisper` | POST | User JWT (Bearer) |  | Warm Transfer Whisper Briefing Called by Twilio's <Number url="..."> when the receiving agent picks up. |
| `agent-ai-translate-campaign-opening` | `…/functions/v1/agent-ai-translate-campaign-opening` | POST | User JWT (Bearer) |  | Thin auth wrapper: invoked from the UI on campaign create/edit to translate the script opening into the campaign language and cache it on |
| `agent-ai-translate-receptionist-greeting` | `…/functions/v1/agent-ai-translate-receptionist-greeting` | POST | User JWT (Bearer) |  | Thin auth wrapper: invoked from the Arwyn Receptionist tab on Save to translate the greeting into the receptionist language and cache it on |
| `agent-ai-tts` | `…/functions/v1/agent-ai-tts` | POST | User JWT (Bearer) |  | Handle CORS preflight requests |
| `agent-ai-voice-explore` | `…/functions/v1/agent-ai-voice-explore` | POST | User JWT (Bearer) |  | Agent AI demo: ElevenLabs Voice Library ("Explore" tab). Called ONLY by the demo Voice tab (src/pages/demo/agentAiDemo/tabs/VoiceTab.tsx). |
| `agent-ai-voice-fallback` | `…/functions/v1/agent-ai-voice-fallback` | POST | User JWT (Bearer) |  | agent-ai-voice-fallback Wired as the Voice URL **Fallback** on every active Twilio number. |
| `agent-builder-ai` | `…/functions/v1/agent-builder-ai` | POST | User JWT (Bearer) |  | agent-builder-ai Lightweight assistant for the AI Agents builder UI. Covers three modes: |
| `agent-builtin-scheduler` | `…/functions/v1/agent-builtin-scheduler` | POST | User JWT (Bearer) | ✓ | Built-in agent scheduler. Cron pings this once; it fans out to every (subaccount, user) tuple that has the agent enabled and invokes the worker. |
| `agent-chat` | `…/functions/v1/agent-chat` | POST | User JWT (Bearer) |  | CMS-aware Medicare & Health Insurance System Prompt This knowledge block enhances understanding of CMS rules, Medicare products, ACA, and transitions. |
| `agent-client-retention` | `…/functions/v1/agent-client-retention` | POST | User JWT (Bearer) |  | Agent Client Retention function. |
| `agent-coverage-opportunity` | `…/functions/v1/agent-coverage-opportunity` | POST | User JWT (Bearer) |  | Medicare Coverage Opportunity Agent Daily cron sweep that flags Medicare-related opportunities and creates tasks for human review. |
| `agent-insights` | `…/functions/v1/agent-insights` | POST | User JWT (Bearer) |  | Create AI prompt based on agent metrics |
| `agent-lead-conversion` | `…/functions/v1/agent-lead-conversion` | POST | User JWT (Bearer) | ✓ | Kill-switch guard |
| `agent-presence` | `…/functions/v1/agent-presence` | POST | User JWT (Bearer) |  | Agent Presence function. |
| `agent-revenue-integrity` | `…/functions/v1/agent-revenue-integrity` | POST | User JWT (Bearer) |  | ---- Normalization helpers (shared by dry-run + live run) ----------------- |
| `agent-user-dispatcher` | `…/functions/v1/agent-user-dispatcher` | POST | User JWT (Bearer) |  | agent-user-dispatcher: runs every minute via pg_cron. Finds active scheduled user_agents and invokes agent-user-executor for those |
| `agent-user-executor` | `…/functions/v1/agent-user-executor` | POST | User JWT (Bearer) | ✓ | agent-user-executor: runs user-built agents (Phase 5 Track B) Loads an agent + its triggers/conditions/actions, evaluates against records, |
| `ai-analytics-insights` | `…/functions/v1/ai-analytics-insights` | POST | User JWT (Bearer) |  | AUTH + SPEND GUARD |
| `ai-analyze-leads` | `…/functions/v1/ai-analyze-leads` | POST | User JWT (Bearer) |  | Fetch leads data |
| `ai-analyze-voice-profile` | `…/functions/v1/ai-analyze-voice-profile` | POST | User JWT (Bearer) |  | Ai Analyze Voice Profile function. |
| `ai-assistant-chat` | `…/functions/v1/ai-assistant-chat` | POST | User JWT (Bearer) |  | Input validation schema |
| `ai-automation-builder` | `…/functions/v1/ai-automation-builder` | POST | User JWT (Bearer) |  | Triggers are described by the model in flat, human terms and must be translated into the shape the config panel and the processors actually read. |
| `ai-build-workflow` | `…/functions/v1/ai-build-workflow` | POST | User JWT (Bearer) |  | Deterministic day math. The model's day arithmetic is not reliable — the same prompt has produced 125, 90 and 75 day spans on consecutive runs — so the |
| `ai-call-coaching` | `…/functions/v1/ai-call-coaching` | POST | User JWT (Bearer) |  | Returns a 200 response with not_ready=true so the UI can render a friendly empty state instead of a generic "non-2xx" error toast. Used when the call |
| `ai-call-summary` | `…/functions/v1/ai-call-summary` | POST | User JWT (Bearer) |  | Ai Call Summary function. |
| `ai-campaign-insights` | `…/functions/v1/ai-campaign-insights` | POST | User JWT (Bearer) |  | AUTH + SPEND GUARD |
| `ai-campaign-reports-insights` | `…/functions/v1/ai-campaign-reports-insights` | POST | User JWT (Bearer) |  | AUTH + SPEND GUARD |
| `ai-chat` | `…/functions/v1/ai-chat` | POST | User JWT (Bearer) |  | SECURITY: Dynamic CORS based on request origin - no more wildcard |
| `ai-chat-suggest-followups` | `…/functions/v1/ai-chat-suggest-followups` | POST | User JWT (Bearer) |  | Ai Chat Suggest Followups function. |
| `ai-commission-intelligence` | `…/functions/v1/ai-commission-intelligence` | POST | User JWT (Bearer) |  | Rate limiting |
| `ai-communication` | `…/functions/v1/ai-communication` | POST | User JWT (Bearer) |  | AUTHENTICATION - Mandatory |
| `ai-deep-research` | `…/functions/v1/ai-deep-research` | POST | User JWT (Bearer) |  | COMPREHENSIVE INSURANCE CARRIER KNOWLEDGE BASE v2 |
| `ai-form-builder` | `…/functions/v1/ai-form-builder` | POST | User JWT (Bearer) |  | AI Form Builder — generates and iterates form field arrays from natural language. Uses Lovable AI gateway with structured tool-calling for reliable JSON output. |
| `ai-generate-content` | `…/functions/v1/ai-generate-content` | POST | User JWT (Bearer) |  | Validation schema |
| `ai-generate-image` | `…/functions/v1/ai-generate-image` | POST | User JWT (Bearer) |  | Select model based on quality |
| `ai-generate-note` | `…/functions/v1/ai-generate-note` | POST | User JWT (Bearer) |  | AUTHENTICATION - Mandatory |
| `ai-generate-pdf` | `…/functions/v1/ai-generate-pdf` | POST | User JWT (Bearer) |  | Ai Generate Pdf function. |
| `ai-generate-sheets` | `…/functions/v1/ai-generate-sheets` | POST | User JWT (Bearer) |  | Ai Generate Sheets function. |
| `ai-generate-slides` | `…/functions/v1/ai-generate-slides` | POST | User JWT (Bearer) |  | Ai Generate Slides function. |
| `ai-generate-sms` | `…/functions/v1/ai-generate-sms` | POST | User JWT (Bearer) |  | AUTHENTICATION - Mandatory |
| `ai-insights` | `…/functions/v1/ai-insights` | POST | User JWT (Bearer) |  | Rate limiting |
| `ai-lead-insights` | `…/functions/v1/ai-lead-insights` | POST | User JWT (Bearer) |  | Get Supabase client |
| `ai-lead-score` | `…/functions/v1/ai-lead-score` | POST | User JWT (Bearer) |  | Deterministic lead scoring engine. Uses subaccount scoring_settings weights + bonus factors (recency, completeness, source quality). |
| `ai-map-csv-columns` | `…/functions/v1/ai-map-csv-columns` | POST | User JWT (Bearer) |  | Which importer is asking. Drives the domain vocabulary in the system prompt. Defaults to "contacts" so existing callers are unaffected. |
| `ai-market-briefing` | `…/functions/v1/ai-market-briefing` | POST | User JWT (Bearer) |  | Ai Market Briefing function. |
| `ai-newsletter-generate` | `…/functions/v1/ai-newsletter-generate` | POST | User JWT (Bearer) |  | Validate auth |
| `ai-pipeline-intelligence` | `…/functions/v1/ai-pipeline-intelligence` | POST | User JWT (Bearer) |  | ------- SSE helpers ------- |
| `ai-policy-intelligence` | `…/functions/v1/ai-policy-intelligence` | POST | User JWT (Bearer) |  | Rate limiting |
| `ai-predictive-insights` | `…/functions/v1/ai-predictive-insights` | POST | User JWT (Bearer) |  | Fetch last 90 days of call logs for this subaccount |
| `ai-sms-reply` | `…/functions/v1/ai-sms-reply` | POST | User JWT (Bearer) |  | AI Chatbot Edge Function (v5 — Intelligence Upgrade) v5 improvements: |
| `ai-suggest-reply` | `…/functions/v1/ai-suggest-reply` | POST | User JWT (Bearer) |  | AUTHENTICATION - Mandatory |
| `ai-task-intelligence` | `…/functions/v1/ai-task-intelligence` | POST | User JWT (Bearer) |  | Rate limiting |
| `ai-tool-drift-check` | `…/functions/v1/ai-tool-drift-check` | POST | User JWT (Bearer) | ✓ | Runs one check; a thrown check degrades to a single info finding. |
| `ai-transform-crm-text` | `…/functions/v1/ai-transform-crm-text` | POST | User JWT (Bearer) |  | Ai Transform Crm Text function. |
| `ai-v2-status` | `…/functions/v1/ai-v2-status` | POST | User JWT (Bearer) |  | unLocked AI v2 — status endpoint. The side panel calls this (passing the currently SELECTED subaccount) to decide |
| `ai-workflow-bundle` | `…/functions/v1/ai-workflow-bundle` | POST | User JWT (Bearer) |  | Map a logical step "tool" to the edge function that executes it. |
| `ai-write-bulk-email` | `…/functions/v1/ai-write-bulk-email` | POST | User JWT (Bearer) |  | Edge function: ai-write-bulk-email Generates a Subject + HTML body for a bulk email using Lovable AI |
| `ai-write-bulk-sms` | `…/functions/v1/ai-write-bulk-sms` | POST | User JWT (Bearer) |  | Edge function: ai-write-bulk-sms Generates a single SMS message body using Lovable AI, scoped to the |

### Admin & Provisioning (14)

| Function | Path | Methods | Auth | Cron | Description |
|---|---|---|---|---|---|
| `add-team-seat` | `…/functions/v1/add-team-seat` | POST | User JWT (Bearer) |  | Claim state, declared out here rather than inside the try so the catch at the bottom can release a claim that was staked and provably never reached Stripe. |
| `admin-ban-user` | `…/functions/v1/admin-ban-user` | POST | User JWT (Bearer) |  | Verify caller is an admin or has internal secret |
| `admin-cancel-account` | `…/functions/v1/admin-cancel-account` | POST | User JWT (Bearer) |  | Verify caller is an admin |
| `admin-eo-compliance` | `…/functions/v1/admin-eo-compliance` | POST | User JWT (Bearer) |  | Verify user identity |
| `admin-legacy-migration-discover` | `…/functions/v1/admin-legacy-migration-discover` | POST | User JWT (Bearer) |  | admin-legacy-migration-discover READ-ONLY lookup for legacy GoHighLevel → unLocked CRM migration. |
| `admin-legacy-migration-migrate` | `…/functions/v1/admin-legacy-migration-migrate` | POST | User JWT (Bearer) |  | admin-legacy-migration-migrate Execute legacy GHL → CRM migration: |
| `admin-provision-user` | `…/functions/v1/admin-provision-user` | POST | User JWT (Bearer) |  | Ensure owner role |
| `provision-user-wallet` | `…/functions/v1/provision-user-wallet` | POST | User JWT (Bearer) |  | provision-user-wallet PHASE 2 — Per-User Per-Subaccount Wallet Infrastructure |
| `remove-team-seat` | `…/functions/v1/remove-team-seat` | POST | User JWT (Bearer) |  | OPTIONAL and additive. Absent means "no key", which is byte-identical to this function's behaviour before it existed — so any caller that does not |
| `temp-fix-login-mj` | `…/functions/v1/temp-fix-login-mj` | POST | User JWT (Bearer) |  | One-shot admin utility — support use only. Target: Manjinder "MJ" Jhamat (Raj Insurance Services) |
| `temp-set-password-brian` | `…/functions/v1/temp-set-password-brian` | POST | User JWT (Bearer) |  | One-shot admin utility — support use only. Target: Brian Bale (brian@tdhinsure.com -> support@tdhinsure.com) |
| `temp-set-password-keela` | `…/functions/v1/temp-set-password-keela` | POST | User JWT (Bearer) |  | One-shot admin utility — support use only. Target: Kellie Solo (kellie@solowealthgroup.com) |
| `temp-set-password-wendy` | `…/functions/v1/temp-set-password-wendy` | POST | User JWT (Bearer) |  | One-shot admin utility — support use only. Target: Wendy Beatty (login email wendy@forefrontbrokersolutions.com) |
| `temp-update-email` | `…/functions/v1/temp-update-email` | POST | User JWT (Bearer) |  | Temp Update Email function. |

### Automation & Scheduled Jobs (31)

| Function | Path | Methods | Auth | Cron | Description |
|---|---|---|---|---|---|
| `capability-nav-report` | `…/functions/v1/capability-nav-report` | POST | User JWT (Bearer) |  | unLocked AI v2 — navigation snapshot intake. The frontend POSTs its current navigation tree here. We authenticate the |
| `capability-scan` | `…/functions/v1/capability-scan` | POST | User JWT (Bearer) | ✓ | unLocked AI v2 — Capability Scan edge function. Thin HTTP wrapper around runFullScan(). Invoked by the Phase 3 pg_cron job |
| `capability-search` | `…/functions/v1/capability-search` | POST | User JWT (Bearer) |  | unLocked AI v2 — Capability Search (test harness). Standalone endpoint to verify the Phase 4 retrieval layer against the live |
| `process-abandoned-checkout` | `…/functions/v1/process-abandoned-checkout` | POST | User JWT (Bearer) |  | Abandoned Checkout Recovery Drip Runs via cron every hour. Finds users who signed up but never completed |
| `process-birthday-reminders` | `…/functions/v1/process-birthday-reminders` | POST | User JWT (Bearer) | ✓ | Local hour, in the workspace's own timezone, at which birthday outreach may start going out. The cron runs hourly and each workspace is skipped until its |
| `process-booking-nudges` | `…/functions/v1/process-booking-nudges` | POST | User JWT (Bearer) | ✓ | Booking-link SMS Nudge scheduler. Runs on a cron (every ~5 minutes). For each upcoming appointment that came |
| `process-campaigns` | `…/functions/v1/process-campaigns` | POST | User JWT (Bearer) | ✓ | BATCH CONFIGURATION FOR SCALE The send-sms ceiling is PER SUBACCOUNT, not global: check_high_cost_rate_limit is called |
| `process-cancellation-drip` | `…/functions/v1/process-cancellation-drip` | POST | User JWT (Bearer) |  | ============= EMAIL TEMPLATE HELPERS ============= |
| `process-custom-date-reminders` | `…/functions/v1/process-custom-date-reminders` | POST | User JWT (Bearer) | ✓ | Local hour, in the workspace's own timezone, at which nudges may start going out. The cron runs hourly and each workspace is skipped until its own clock |
| `process-enrollment-period` | `…/functions/v1/process-enrollment-period` | POST | User JWT (Bearer) | ✓ | process-enrollment-period Server-side replacement for the client-only useEnrollmentPeriodScanner hook. |
| `process-medicare-eligibility` | `…/functions/v1/process-medicare-eligibility` | POST | User JWT (Bearer) | ✓ | The age being turned. 65 (Medicare IEP) unless the workflow says otherwise. |
| `process-medicare-pending-eligible` | `…/functions/v1/process-medicare-pending-eligible` | POST | User JWT (Bearer) | ✓ | process-medicare-pending-eligible Server-side firing engine for the "Medicare Pending → Eligible" trigger |
| `process-nipr-alert-billing` | `…/functions/v1/process-nipr-alert-billing` | POST | User JWT (Bearer) |  | NIPR PDB ALERT MONTHLY BILLING Scheduled job to process monthly alert subscriptions |
| `process-onboarding-emails` | `…/functions/v1/process-onboarding-emails` | POST | User JWT (Bearer) |  | Subaccounts whose members should NOT receive onboarding drip emails |
| `process-onboarding-queue` | `…/functions/v1/process-onboarding-queue` | POST | User JWT (Bearer) |  | Processes the scheduled_onboarding_emails queue. Runs every minute via pg_cron. Picks up rows where send_at <= now() and sent = false, |
| `process-policy-renewal` | `…/functions/v1/process-policy-renewal` | POST | User JWT (Bearer) | ✓ | process-policy-renewal Server-side replacement for the client-only useRenewalScanner hook. The |
| `process-quote-attachment` | `…/functions/v1/process-quote-attachment` | POST | User JWT (Bearer) |  | Process Quote Attachment function. |
| `process-resend-unopened` | `…/functions/v1/process-resend-unopened` | POST | Provider webhook signature |  | Find campaigns with resendToUnopened enabled that are past their delay window |
| `process-scheduled-emails` | `…/functions/v1/process-scheduled-emails` | POST | User JWT (Bearer) |  | Load a scheduled campaign's attachments once, up front, so the bytes are reused across every recipient instead of being re-downloaded per send. |
| `process-scheduled-nudges` | `…/functions/v1/process-scheduled-nudges` | POST | User JWT (Bearer) | ✓ | Process Scheduled Nudges This edge function processes pending scheduled messages from the scheduled_messages table. |
| `process-scheduled-opportunities` | `…/functions/v1/process-scheduled-opportunities` | POST | User JWT (Bearer) | ✓ | Processes due rows in scheduled_opportunity_additions (Contacts → "Add/Update Opportunity", Scheduled & Drip modes). For each due row it creates the real |
| `process-scheduled-quote-sends` | `…/functions/v1/process-scheduled-quote-sends` | POST | User JWT (Bearer) | ✓ | Cron-driven processor that sends due scheduled quotes. Reads scheduled_quote_sends where status='pending' AND scheduled_for <= now(), |
| `process-sms-queue` | `…/functions/v1/process-sms-queue` | POST | User JWT (Bearer) |  | SMS Queue Processor — consumes sms_send_queue rows that were deferred due to 10DLC throughput limits (1 msg/sec/number). |
| `process-task-reminders` | `…/functions/v1/process-task-reminders` | POST | User JWT (Bearer) |  | Get current date (UTC midnight for comparison) |
| `process-workflow-jobs` | `…/functions/v1/process-workflow-jobs` | POST | User JWT (Bearer) |  | process-workflow-jobs (legacy compatibility entrypoint) Keep this function as a thin proxy only. The real processor is |
| `trigger-day0-onboarding` | `…/functions/v1/trigger-day0-onboarding` | POST | User JWT (Bearer) |  | Triggers Day 0 onboarding emails with staggered delays: - day0_welcome: immediately |
| `trigger-link-click` | `…/functions/v1/trigger-link-click` | POST | User JWT (Bearer) |  | Public endpoint hit when the React route /l/:slug loads. Records the click, fires trigger-workflow with triggerType='trigger_link_clicked' so any paused |
| `trigger-workflow` | `…/functions/v1/trigger-workflow` | POST | User JWT (Bearer) | ✓ | BOOKING LINK SAFEGUARD When a user has no active booking link, {{booking_link}}, {{user.calendar_link}}, |
| `webhook-dispatcher` | `…/functions/v1/webhook-dispatcher` | POST | Provider webhook signature | ✓ | Outbound webhook dispatcher. POST /functions/v1/webhook-dispatcher |
| `webhook-retry-worker` | `…/functions/v1/webhook-retry-worker` | POST | Provider webhook signature | ✓ | Webhook delivery retry worker Re-attempts failed webhook deliveries with exponential backoff: |
| `workflow-queue-listener` | `…/functions/v1/workflow-queue-listener` | POST | User JWT (Bearer) | ✓ | workflow-queue-listener Event-driven workflow job processor. Invoked by: |

### Billing & Payments (15)

| Function | Path | Methods | Auth | Cron | Description |
|---|---|---|---|---|---|
| `check-subscription` | `…/functions/v1/check-subscription` | POST | User JWT (Bearer) |  | Safely convert Stripe's current_period_end (unix seconds or already a Date/string) to ISO string |
| `commission-plus-activate` | `…/functions/v1/commission-plus-activate` | POST | User JWT (Bearer) |  | Commission Plus Activate function. |
| `create-checkout` | `…/functions/v1/create-checkout` | POST | User JWT (Bearer) |  | Server-side validation: only allow known Stripe price IDs |
| `deduct-wallet` | `…/functions/v1/deduct-wallet` | POST | User JWT (Bearer) |  | Context: docs/source-of-truth/BILLING_WALLET_SOURCE_OF_TRUTH.md |
| `lead-cap-billing-trigger` | `…/functions/v1/lead-cap-billing-trigger` | POST | User JWT (Bearer) | ✓ | Lead Cap Billing Trigger Invoked by DB trigger when an agent's remaining lead balance crosses the |
| `manual-recharge` | `…/functions/v1/manual-recharge` | POST | User JWT (Bearer) |  | Fund amounts available for wallet top-up (all in USD) |
| `marketplace-checkout` | `…/functions/v1/marketplace-checkout` | POST | User JWT (Bearer) |  | Get authenticated user |
| `rebill-subaccount` | `…/functions/v1/rebill-subaccount` | POST | User JWT (Bearer) |  | Call atomic rebill RPC — handles vendor cost deduction from agency wallet and markup-based deduction from sub-account wallet in a single transaction |
| `self-cancel-subscription` | `…/functions/v1/self-cancel-subscription` | POST | User JWT (Bearer) |  | The target `team_members` row, as read here. `TargetTeamMemberRow` is the subset authorizeMemberCancel decides on; the rest is what this handler needs |
| `stripe-advanced-support-webhook` | `…/functions/v1/stripe-advanced-support-webhook` | POST | Provider webhook signature |  | Helper function to send emails via Resend API (no SDK needed) |
| `stripe-kaleb-preview` | `…/functions/v1/stripe-kaleb-preview` | POST | User JWT (Bearer) |  | Temporary read-only diagnostic function — see docs/client-kaleb-dodson-upgrade-button/PREVIEW_FUNCTION_TECHNICAL.md |
| `stripe-max-audit` | `…/functions/v1/stripe-max-audit` | POST | User JWT (Bearer) |  | Temporary read-only audit function — see docs/client-kaleb-dodson-upgrade-button/ for the Kaleb investigation that triggered this. Surveys Max-plan subscriptions |
| `stripe-trial-audit-readonly` | `…/functions/v1/stripe-trial-audit-readonly` | POST | User JWT (Bearer) |  | TEMPORARY READ-ONLY audit function. Delete after use. Split into modes to stay under gateway timeout: ?mode=failed\|trialing\|descriptor |
| `stripe-webhook` | `…/functions/v1/stripe-webhook` | POST | Provider webhook signature |  | Safely convert Stripe's current_period_end (unix seconds or already a Date/string) to ISO string |
| `trigger-auto-recharge` | `…/functions/v1/trigger-auto-recharge` | POST | User JWT (Bearer) |  | Recharge tiers for smart adjustment |

### Calendar & Booking (1)

| Function | Path | Methods | Auth | Cron | Description |
|---|---|---|---|---|---|
| `calendar-cron-sync` | `…/functions/v1/calendar-cron-sync` | POST | User JWT (Bearer) |  | Server-side cron sync for calendar events Runs every 5 minutes as a fallback safety net |

### Core CRM (200)

| Function | Path | Methods | Auth | Cron | Description |
|---|---|---|---|---|---|
| `add-mailgun-domain` | `…/functions/v1/add-mailgun-domain` | POST | Provider webhook signature |  | Same resolution as verify-mailgun-domain and send-mailgun, so the domain is created in the account that will later be asked to verify it and send from it. |
| `analyze-policy` | `…/functions/v1/analyze-policy` | POST | User JWT (Bearer) |  | ===== SCANNED PDF / OCR DETECTION ===== Detect if a PDF is scanned (image-based) vs native (text-based) |
| `apply-invoice-coupon` | `…/functions/v1/apply-invoice-coupon` | POST | User JWT (Bearer) |  | Apply Invoice Coupon function. |
| `archive-audit-logs` | `…/functions/v1/archive-audit-logs` | POST | User JWT (Bearer) |  | Archive Audit Logs Edge Function PURPOSE: |
| `at-risk-trial-alert` | `…/functions/v1/at-risk-trial-alert` | POST | User JWT (Bearer) |  | Fetch all trialing subscriptions |
| `atlas-search` | `…/functions/v1/atlas-search` | POST | User JWT (Bearer) |  | State abbreviation mapping |
| `backfill-onboarding-pdfs` | `…/functions/v1/backfill-onboarding-pdfs` | POST | User JWT (Bearer) |  | One-shot backfill: re-sends the onboarding PDF email for users who completed onboarding in the last N days but whose admin notification never went out |
| `backfill-script-standard` | `…/functions/v1/backfill-script-standard` | POST | User JWT (Bearer) |  | backfill-script-standard Re-runnable sweep that brings agent_ai_scripts rows into full compliance with the |
| `backfill-wallet-payment-methods` | `…/functions/v1/backfill-wallet-payment-methods` | POST | User JWT (Bearer) |  | BACKFILL: Populate credit_wallets.default_payment_method_id from Stripe One-time admin script. NOT scheduled. NOT invoked automatically. |
| `build-compile` | `…/functions/v1/build-compile` | POST | User JWT (Bearer) |  | build-compile — Build v2 sandboxed code-gen pipeline. POST { source: string } |
| `build-edit-widget` | `…/functions/v1/build-edit-widget` | POST | User JWT (Bearer) |  | build-edit-widget Targeted, single-widget AI editing. |
| `build-entity-write` | `…/functions/v1/build-entity-write` | POST | User JWT (Bearer) |  | Entities that are READ-ONLY through the Build write surface. Reads still work via CRM.query / entity_table widgets; writes are blocked because they have |
| `build-generate` | `…/functions/v1/build-generate` | POST | User JWT (Bearer) |  | Generatable widget types (the AI tool-schema enum). EDGE-FN copy — MUST stay in sync with ALLOWED_WIDGET_TYPES in src/lib/builderValidation.ts. Locked by widgetTypeSync.test.ts. |
| `build-generate-code` | `…/functions/v1/build-generate-code` | POST | User JWT (Bearer) |  | build-generate-code — Build v2 generator (TSX + sandbox). POST { |
| `build-page-event` | `…/functions/v1/build-page-event` | POST | User JWT (Bearer) |  | build-page-event — Phase 4 dispatcher Single entrypoint for Page Automations. Looks up matching automations for a |
| `build-rollback` | `…/functions/v1/build-rollback` | POST | User JWT (Bearer) |  | build-rollback — restore a previously applied Build AI artifact. Permission model: |
| `build-safe-query` | `…/functions/v1/build-safe-query` | POST | User JWT (Bearer) |  | AI Safe Query Builder Translates natural-language analytics questions into safe, parameterized |
| `build-suggest-binding` | `…/functions/v1/build-suggest-binding` | POST | User JWT (Bearer) |  | build-suggest-binding AI-assisted data binding for the Build module. |
| `build-website-generate` | `…/functions/v1/build-website-generate` | POST | User JWT (Bearer) |  | build-website-generate — AI generator for PUBLIC insurance marketing sites & landing pages. Deliberately isolated from build-generate (the CRM dashboard generator): a marketing |
| `campaign-availability` | `…/functions/v1/campaign-availability` | POST | User JWT (Bearer) |  | Auth via API key |
| `campaign-lead-ping` | `…/functions/v1/campaign-lead-ping` | POST | User JWT (Bearer) |  | Auth via API key |
| `check-secrets` | `…/functions/v1/check-secrets` | POST | Provider webhook signature |  | List of all secrets we want to check |
| `check-stale-leads-sla` | `…/functions/v1/check-stale-leads-sla` | POST | User JWT (Bearer) |  | Scheduled edge function (weekly cron) that: #51 — Sends stale lead digest (leads with no activity 14+ days, status ≠ Won/Lost) |
| `check-stale-tickets` | `…/functions/v1/check-stale-tickets` | POST | User JWT (Bearer) |  | Auth: cron secret |
| `check-tasks-appointments` | `…/functions/v1/check-tasks-appointments` | POST | User JWT (Bearer) |  | Scheduled edge function that handles: #53 — Tasks due today (morning digest, in-app + email) |
| `check-whitelabel-dns` | `…/functions/v1/check-whitelabel-dns` | POST | User JWT (Bearer) |  | Verifies DNS for a self-serve white-label custom domain. Checks that both the root domain and its `www` variant resolve |
| `claim-team-seat` | `…/functions/v1/claim-team-seat` | POST | User JWT (Bearer) |  | Context: docs/source-of-truth/TEAM_INVITES_SOURCE_OF_TRUTH.md §15 (and §14 for the release side, which is unchanged here). |
| `cms-evaluate-eligibility` | `…/functions/v1/cms-evaluate-eligibility` | POST | User JWT (Bearer) |  | IEP starts 3 months before 65th birthday month |
| `complete-agent-payment-setup` | `…/functions/v1/complete-agent-payment-setup` | POST | User JWT (Bearer) |  | Try JWT auth first (works for both paths) |
| `compute-health-scores` | `…/functions/v1/compute-health-scores` | POST | User JWT (Bearer) |  | Fetch all subaccounts |
| `connect-icloud-calendar` | `…/functions/v1/connect-icloud-calendar` | POST | User JWT (Bearer) |  | Validate inputs |
| `contact-intelligence` | `…/functions/v1/contact-intelligence` | POST | User JWT (Bearer) |  | Verify user authentication |
| `create-data-checkout` | `…/functions/v1/create-data-checkout` | POST | User JWT (Bearer) |  | Licensed Agent Data product price IDs |
| `create-mailgun-inbound-route` | `…/functions/v1/create-mailgun-inbound-route` | POST | User JWT (Bearer) |  | Handle CORS preflight |
| `create-notification` | `…/functions/v1/create-notification` | POST | User JWT (Bearer) |  | Rate limiting |
| `create-portal-session` | `…/functions/v1/create-portal-session` | POST | User JWT (Bearer) |  | Find the user's Stripe customer ID |
| `create-team-user` | `…/functions/v1/create-team-user` | POST | User JWT (Bearer) |  | Create Team User Edge Function SECURITY: Admin-only endpoint with restricted CORS |
| `create-tiktok-review-user` | `…/functions/v1/create-tiktok-review-user` | POST | User JWT (Bearer) |  | Create TikTok Review User - Admin-only endpoint SECURITY: This function requires admin authentication and reads |
| `daily-no-call-digest` | `…/functions/v1/daily-no-call-digest` | POST | User JWT (Bearer) |  | onboarding progress |
| `data-proxy` | `…/functions/v1/data-proxy` | POST | User JWT (Bearer) |  | Initialize Supabase URL and anon key |
| `decay-memories` | `…/functions/v1/decay-memories` | POST | User JWT (Bearer) |  | Memory Decay Logic Reduces the relevance_weight of memories over time based on: |
| `delete-appointment` | `…/functions/v1/delete-appointment` | POST | User JWT (Bearer) |  | ===== Google helpers ===== |
| `delete-conversation` | `…/functions/v1/delete-conversation` | POST | User JWT (Bearer) |  | Authorized, complete deletion of a conversation (thread) from the Inbox. The client-side delete could only remove interaction rows the caller personally |
| `delete-secret` | `…/functions/v1/delete-secret` | POST | User JWT (Bearer) |  | Get environment variables once at the start |
| `delete-team-user` | `…/functions/v1/delete-team-user` | POST | User JWT (Bearer) |  | Delete Team User Edge Function SECURITY: Admin-only endpoint with restricted CORS |
| `diag-el-audit` | `…/functions/v1/diag-el-audit` | POST | User JWT (Bearer) |  | Diag El Audit function. |
| `diag-elevenlabs-pilot` | `…/functions/v1/diag-elevenlabs-pilot` | POST | User JWT (Bearer) |  | Diag Elevenlabs Pilot function. |
| `diag-inbound-routing` | `…/functions/v1/diag-inbound-routing` | POST | User JWT (Bearer) |  | diag-inbound-routing — RETIRED. Returns 410 Gone. Was a read-only diagnostic for the 2026-08-18 inbound-routing incident on |
| `diag-incident-1258` | `…/functions/v1/diag-incident-1258` | GET, POST | User JWT (Bearer) |  | READ-ONLY incident diagnostic for the 12:58Z regression on +15717123991 / phnum_9901. Calls EL GET /v1/convai/phone-numbers/{id} and Twilio GET /IncomingPhoneNumbers/{sid}.json. |
| `diag-meta-page-discovery` | `…/functions/v1/diag-meta-page-discovery` | POST | Provider webhook signature |  | READ-ONLY diagnostic for Ticket-655 — "only one Facebook Page appears under Available Pages". Answers, from Facebook itself rather than from our stored copy, WHY a Page is missing. |
| `disconnect-nipr` | `…/functions/v1/disconnect-nipr` | POST | User JWT (Bearer) |  | Verify the user has access to this subaccount |
| `domains-provision` | `…/functions/v1/domains-provision` | POST | User JWT (Bearer) |  | domains-provision (authenticated) — connect a custom domain to a website. Validates the caller owns the website, asks Cloudflare (or the stub adapter) to create a |
| `domains-verify` | `…/functions/v1/domains-verify` | POST | User JWT (Bearer) |  | domains-verify (authenticated) — re-check a custom domain's DNS/SSL status with Cloudflare and update the `domains` row. When status becomes "active", render-website will serve it. |
| `downline-ai-insights` | `…/functions/v1/downline-ai-insights` | POST | User JWT (Bearer) |  | Downline Ai Insights function. |
| `drug-intake-chat` | `…/functions/v1/drug-intake-chat` | POST | User JWT (Bearer) |  | Conversational AI Drug Intake Walks through medication capture via Q&A, asking follow-ups for dosage/frequency, |
| `el-pilot-diag` | `…/functions/v1/el-pilot-diag` | POST | Tool secret (`X-Tool-Secret`) |  | Temporary read-only diagnostic for EL pilot env + EL dashboard pull. No secrets are echoed. Returns presence/length/last4 only. |
| `elevenlabs-audio-isolation` | `…/functions/v1/elevenlabs-audio-isolation` | POST | User JWT (Bearer) |  | ElevenLabs Audio Isolation Edge Function Cleans noisy call recordings by isolating speech from background noise. |
| `elevenlabs-dubbing` | `…/functions/v1/elevenlabs-dubbing` | POST | User JWT (Bearer) |  | ElevenLabs Dubbing / Multi-language Edge Function Auto-translates agent AI scripts into other languages while preserving |
| `elevenlabs-tts` | `…/functions/v1/elevenlabs-tts` | POST | User JWT (Bearer) |  | Default to turbo v2.5 for speed (power dialer greetings, live scenarios) Use multilingual only when explicitly requested for quality |
| `embed-email-calendar` | `…/functions/v1/embed-email-calendar` | POST | User JWT (Bearer) |  | deno-lint-ignore-file no-explicit-any Background worker: generates 768-dim embeddings for emails + appointments |
| `embed-knowledge` | `…/functions/v1/embed-knowledge` | POST | User JWT (Bearer) |  | ===== IMPROVED CHUNKING: Section-aware with better overlap ===== |
| `end-impersonation` | `…/functions/v1/end-impersonation` | POST | User JWT (Bearer) |  | End Impersonation Edge Function SECURITY: Authenticated endpoint with restricted CORS |
| `enroll-campaign-contacts` | `…/functions/v1/enroll-campaign-contacts` | POST | User JWT (Bearer) |  | Get user from auth header |
| `execute-math-operation` | `…/functions/v1/execute-math-operation` | POST | User JWT (Bearer) |  | Get the contact to retrieve current field value |
| `extract-insurance-dictation` | `…/functions/v1/extract-insurance-dictation` | POST | User JWT (Bearer) |  | Extract Insurance Dictation function. |
| `extract-memories` | `…/functions/v1/extract-memories` | POST | User JWT (Bearer) |  | Call Lovable AI for extraction |
| `family-tree-insights` | `…/functions/v1/family-tree-insights` | POST | User JWT (Bearer) |  | Family Tree Insights function. |
| `fetch-nipr-entity` | `…/functions/v1/fetch-nipr-entity` | POST | User JWT (Bearer) |  | ─── Retry wrapper ──────────────────────────────────────────────────────────── |
| `fetch-twilio-full-recording` | `…/functions/v1/fetch-twilio-full-recording` | POST | Provider webhook signature |  | fetch-twilio-full-recording Stage 2.10 background sweep. For each `agent_ai_call_logs` row queued with |
| `fetch-twilio-recording` | `…/functions/v1/fetch-twilio-recording` | GET, POST | Provider webhook signature |  | Fetch Twilio Recording function. |
| `fraud-monitor` | `…/functions/v1/fraud-monitor` | POST | User JWT (Bearer) |  | Fraud monitor: scans recent signup_attempts and fires Slack alerts on suspicious activity. Designed to be called every 2 minutes by a cron / scheduler. Requires CRON_SECRET header. |
| `generate-admin-update` | `…/functions/v1/generate-admin-update` | POST | User JWT (Bearer) |  | Generate Admin Update function. |
| `generate-call-identity-vcf` | `…/functions/v1/generate-call-identity-vcf` | POST | User JWT (Bearer) |  | Generate Call Identity Vcf function. |
| `generate-call-summary` | `…/functions/v1/generate-call-summary` | POST | User JWT (Bearer) |  | Look up call context (direction, agent, contact) BEFORE the AI call so the model never inverts agent vs. contact roles. This mirrors the same fix |
| `generate-commission-insights` | `…/functions/v1/generate-commission-insights` | POST | User JWT (Bearer) |  | Generate Commission Insights function. |
| `generate-ics-invite` | `…/functions/v1/generate-ics-invite` | POST | User JWT (Bearer) |  | Format date to ICS format: YYYYMMDDTHHMMSSZ |
| `generate-onboarding-checklist` | `…/functions/v1/generate-onboarding-checklist` | POST | User JWT (Bearer) |  | Canonical feature catalog — the AI may ONLY select from these category: "ready" = auto-activated, "assisted" = team will help |
| `generate-retirement-pdf` | `…/functions/v1/generate-retirement-pdf` | POST | User JWT (Bearer) |  | Generate Retirement Pdf function. |
| `generate-soa-pdf` | `…/functions/v1/generate-soa-pdf` | POST | User JWT (Bearer) |  | Generate Soa Pdf function. |
| `get-call-transcript` | `…/functions/v1/get-call-transcript` | POST | User JWT (Bearer) |  | Returns the transcript for a call_recording or agent_ai_call_log. If transcript is missing but a recording_url exists, performs on-demand |
| `get-campaign-stats` | `…/functions/v1/get-campaign-stats` | POST | User JWT (Bearer) |  | Use user JWT to respect RLS |
| `get-downline-data` | `…/functions/v1/get-downline-data` | POST | User JWT (Bearer) |  | Validate user |
| `get-meeting-credentials` | `…/functions/v1/get-meeting-credentials` | POST | User JWT (Bearer) |  | supabase/functions/get-meeting-credentials/index.ts SECURITY: Returns Zoom meeting credentials (join URL, start URL, password, |
| `get-owner-plan-info` | `…/functions/v1/get-owner-plan-info` | POST | User JWT (Bearer) |  | Get Owner Plan Info function. |
| `get-stripe-publishable-key` | `…/functions/v1/get-stripe-publishable-key` | POST | User JWT (Bearer) |  | Get Stripe Publishable Key function. |
| `get-wallet` | `…/functions/v1/get-wallet` | POST | User JWT (Bearer) |  | Recharge tiers for smart adjustment |
| `grant-trial-bonus-day` | `…/functions/v1/grant-trial-bonus-day` | POST | User JWT (Bearer) |  | Daily cron: extend Stripe trial by 1 day for users whose AI took a real action yesterday, up to 7 bonus days. Triggered by pg_cron at 03:00 UTC. |
| `impersonate-user` | `…/functions/v1/impersonate-user` | POST | User JWT (Bearer) |  | Impersonate User Edge Function SECURITY: Admin-only endpoint with restricted CORS |
| `inbound-email-webhook` | `…/functions/v1/inbound-email-webhook` | GET, POST | Provider webhook signature |  | Verify Mailgun webhook signature (HMAC-SHA256) Mailgun signs webhooks with: signature = HMAC(SHA256, signing-key, timestamp + token) |
| `inbound-webhook` | `…/functions/v1/inbound-webhook` | POST | Provider webhook signature |  | Handle CORS preflight |
| `ingest-knowledge-pack` | `…/functions/v1/ingest-knowledge-pack` | POST | User JWT (Bearer) |  | ingest-knowledge-pack — platform admin uploads a carrier knowledge source (UW guide, brochure, rate sheet, commission schedule) and embeds it into |
| `insurance-news` | `…/functions/v1/insurance-news` | POST | User JWT (Bearer) |  | Run all queries in parallel instead of sequentially |
| `internal-backfill-weiss-dryrun` | `…/functions/v1/internal-backfill-weiss-dryrun` | POST | User JWT (Bearer) |  | One-shot dry-run wrapper for Richard Weiss Outlook backfill |
| `itk-quote` | `…/functions/v1/itk-quote` | POST | User JWT (Bearer) |  | itk-quote — Final Expense, Term & IUL quoting via Insurance Toolkits API (redeploy: pickup ITK_API_KEY) REQUIRED SUPABASE SECRETS: |
| `list-team-users` | `…/functions/v1/list-team-users` | POST | User JWT (Bearer) |  | List Team Users Edge Function SECURITY: Admin-only endpoint with restricted CORS |
| `load-recent-webhook-sample` | `…/functions/v1/load-recent-webhook-sample` | POST | Provider webhook signature |  | Verify access |
| `local-presence-reputation-check` | `…/functions/v1/local-presence-reputation-check` | POST | User JWT (Bearer) |  | Provider hook: returns null when no reputation provider is configured, which is currently always. Returning null is the designed no-op — the caller's |
| `log-admin-action` | `…/functions/v1/log-admin-action` | POST | User JWT (Bearer) |  | Log Admin Action Edge Function SECURITY: Admin-only endpoint with restricted CORS |
| `login-rate-limit` | `…/functions/v1/login-rate-limit` | POST | User JWT (Bearer) |  | Server-Side Login Rate Limiter Edge Function Checks and records failed login attempts per (email + IP). |
| `mcp-server` | `…/functions/v1/mcp-server` | POST | API key (`x-api-key`) |  | MCP (Model Context Protocol) server wrapper around the unLocked Public API. Lets AI agents (ChatGPT, Claude, Cursor) discover and call CRM tools natively. |
| `medicare-ppl-explain` | `…/functions/v1/medicare-ppl-explain` | POST | User JWT (Bearer) |  | Handle CORS preflight requests |
| `medicare-public-quote` | `…/functions/v1/medicare-public-quote` | POST | User JWT (Bearer) |  | Another adult in the household. Most Medigap carriers publish a discount for this — commonly 5–14% — and an agent applies it, so omitting it quoted |
| `npi-search` | `…/functions/v1/npi-search` | POST | User JWT (Bearer) |  | NPI Registry proxy - keeps NPPES traffic off the browser so the Lovable preview proxy / CORS quirks can't drop the request. |
| `oauth-callback` | `…/functions/v1/oauth-callback` | POST | User JWT (Bearer) |  | Rate limiting for security |
| `oauth-init` | `…/functions/v1/oauth-init` | POST | User JWT (Bearer) |  | Optional `login_hint`: pre-selects an account on the provider's chooser when the user has several signed in. It is a HINT only — the provider still shows its own sign-in and the user |
| `oauth-server` | `…/functions/v1/oauth-server` | GET, POST | User JWT (Bearer) |  | OAuth 2.0 Server for unLocked CRM Public API. Implements RFC 6749 (Authorization Code) + RFC 7636 (PKCE) + RFC 7009 (Revocation). |
| `onboarding-purchase-number` | `…/functions/v1/onboarding-purchase-number` | POST | User JWT (Bearer) |  | Onboarding wrapper around `twilio-phone-numbers` that automatically comps the very first phone number a subaccount has ever owned. Subsequent numbers |
| `openai-service` | `…/functions/v1/openai-service` | POST | User JWT (Bearer) |  | Build messages array |
| `openapi-spec` | `…/functions/v1/openapi-spec` | POST | User JWT (Bearer) |  | OpenAPI 3.1 specification for the unLocked CRM Public API. Served as a static JSON document so that AI agents (ChatGPT, Claude, |
| `parse-drugs` | `…/functions/v1/parse-drugs` | POST | User JWT (Bearer) |  | If image provided, run OCR via Gemini vision |
| `parse-eo-document` | `…/functions/v1/parse-eo-document` | POST | User JWT (Bearer) |  | Get user from token |
| `parse-pdf` | `…/functions/v1/parse-pdf` | POST | User JWT (Bearer) |  | Step 1: Try text extraction (handles both compressed and uncompressed streams) |
| `parse-providers` | `…/functions/v1/parse-providers` | POST | User JWT (Bearer) |  | Parse Providers function. |
| `portal-activation-notify` | `…/functions/v1/portal-activation-notify` | POST | User JWT (Bearer) |  | Sends two emails when a client first activates their portal: 1) Welcome email to the client |
| `portal-book-appointment` | `…/functions/v1/portal-book-appointment` | POST | User JWT (Bearer) |  | Books an appointment from the client portal. Reuses the agent's CRM availability rules + merges Google/Outlook busy |
| `postmaster-fetch` | `…/functions/v1/postmaster-fetch` | POST | User JWT (Bearer) |  | Get authenticated user |
| `prospector-webhook` | `…/functions/v1/prospector-webhook` | POST | Provider webhook signature |  | Prospector → CRM Webhook (Phase 2) Phase 2 additions: |
| `provider-calendar-event` | `…/functions/v1/provider-calendar-event` | POST | User JWT (Bearer) |  | Push, update, cancel, and RSVP calendar events directly on the user's connected Google Calendar or Outlook Calendar via their OAuth tokens. |
| `proxy-twilio-recording` | `…/functions/v1/proxy-twilio-recording` | POST | User JWT (Bearer) |  | Proxy Twilio Recording function. |
| `public-api` | `…/functions/v1/public-api` | POST | API key (`x-api-key`) |  | Public REST API v1 for unLocked CRM Authenticated via API keys (x-api-key header) |
| `public-appointment-cancel` | `…/functions/v1/public-appointment-cancel` | POST | User JWT (Bearer) |  | ===== Google helpers ===== |
| `public-appointment-reschedule` | `…/functions/v1/public-appointment-reschedule` | POST | User JWT (Bearer) |  | ===== Google helpers ===== |
| `recalculate-all-scores` | `…/functions/v1/recalculate-all-scores` | POST | User JWT (Bearer) |  | Get user's subaccount_id for proper isolation |
| `recompute-agent-profile` | `…/functions/v1/recompute-agent-profile` | POST | User JWT (Bearer) |  | Recomputes agent_ai_profiles for one user (on-demand) or all users (cron) |
| `reconcile-seats` | `…/functions/v1/reconcile-seats` | POST | User JWT (Bearer) |  | ─── AUTH: cron secret or service role ─── |
| `record-call` | `…/functions/v1/record-call` | POST | User JWT (Bearer) |  | Get authorization header |
| `recover-missed-onboarding` | `…/functions/v1/recover-missed-onboarding` | POST | User JWT (Bearer) | ✓ | Auth: accept anon key (from cron), cron secret header, or service role pg_cron calls with anon key Bearer token which passes Supabase gateway auth |
| `refresh-oauth-tokens` | `…/functions/v1/refresh-oauth-tokens` | POST | User JWT (Bearer) |  | Check if token needs encryption by trying to decrypt it Returns true if token needs to be encrypted (is plaintext or encrypted with wrong key) |
| `render-website` | `…/functions/v1/render-website` | POST | User JWT (Bearer) |  | Public website renderer (verify_jwt = false). Resolves the incoming custom-domain host (X-Forwarded-Host, set by the Cloudflare |
| `repair-el-inbound-webhook` | `…/functions/v1/repair-el-inbound-webhook` | POST | User JWT (Bearer) |  | repair-el-inbound-webhook — RETIRED. Returns 410 Gone. Was a one-off repair that rewrote a Twilio number's VoiceUrl and |
| `report-export` | `…/functions/v1/report-export` | POST | User JWT (Bearer) |  | report-export — robust server-side CSV export for the Custom Report Builder. The browser sends a fully-resolved ExportPlan (see src/lib/reportExport.ts); |
| `resolve-zip-counties` | `…/functions/v1/resolve-zip-counties` | POST | User JWT (Bearer) |  | ZIP -> counties, from the CMS marketplace API. WHY THIS EXISTS. Correcting IA Agency's county data needs an authoritative ZIP -> county |
| `resume-scheduled-workflows` | `…/functions/v1/resume-scheduled-workflows` | POST | User JWT (Bearer) |  | resume-scheduled-workflows Background cron job that: |
| `retireflo-intake` | `…/functions/v1/retireflo-intake` | POST | User JWT (Bearer) |  | RetireFlo survey intake → creates/updates a lead, tags Medicare or ACA. Tag-based workflows ("contact_tag_added" trigger) handle the drip. |
| `retirement-crm-automation` | `…/functions/v1/retirement-crm-automation` | POST | User JWT (Bearer) |  | Retirement Crm Automation function. |
| `retry-workflow-run` | `…/functions/v1/retry-workflow-run` | POST | User JWT (Bearer) |  | retry-workflow-run — re-queue a failed workflow execution by re-invoking trigger-workflow with the original trigger_data. Used by the support chat inline "Retry this run" action. |
| `revert-workflow-snapshot` | `…/functions/v1/revert-workflow-snapshot` | POST | User JWT (Bearer) |  | Verify the user owns the workflow (or shares its subaccount) |
| `rotate-api-key` | `…/functions/v1/rotate-api-key` | POST | User JWT (Bearer) |  | Rotate API Key Edge Function SECURITY: Admin-only endpoint with restricted CORS |
| `rotate-encryption-key` | `…/functions/v1/rotate-encryption-key` | POST | User JWT (Bearer) |  | CRITICAL SECURITY FUNCTION Rotates the OAuth encryption key by re-encrypting all tokens |
| `save-secret` | `…/functions/v1/save-secret` | POST | User JWT (Bearer) |  | Get environment variables once at the start |
| `search-knowledge-packs` | `…/functions/v1/search-knowledge-packs` | POST | User JWT (Bearer) |  | search-knowledge-packs — semantic search across platform-curated carrier knowledge. Any authenticated user can call this. Returns chunks with |
| `secure-update-role` | `…/functions/v1/secure-update-role` | POST | User JWT (Bearer) |  | SECURITY: Secure Role Update Edge Function This function handles role changes with proper authorization checks. |
| `security-audit-reminder` | `…/functions/v1/security-audit-reminder` | POST | User JWT (Bearer) |  | Security Audit Reminder Edge Function Sends quarterly reminders to admins to perform security audits |
| `seed-vault-from-env` | `…/functions/v1/seed-vault-from-env` | POST | User JWT (Bearer) |  | seed-vault-from-env One-time / repeatable admin tool to migrate secrets from the Lovable env store |
| `set-sample-listening` | `…/functions/v1/set-sample-listening` | POST | User JWT (Bearer) |  | Look up workflow for ownership/membership check |
| `setup-agent-payment-method` | `…/functions/v1/setup-agent-payment-method` | POST | User JWT (Bearer) |  | Authenticate caller |
| `setup-whitelabel-payment-method` | `…/functions/v1/setup-whitelabel-payment-method` | POST | User JWT (Bearer) |  | White-label subaccounts that support agent payment setup via the generalized page. Add future white-label client subaccount IDs here. |
| `signup-guard` | `…/functions/v1/signup-guard` | POST | User JWT (Bearer) |  | Pre-signup guard: checks IP + email against blocklists before allowing signup. Also logs every attempt to signup_attempts for monitoring + auto-rolling domain blocks. |
| `soa-create-appointment` | `…/functions/v1/soa-create-appointment` | POST | User JWT (Bearer) |  | Creates the calendar appointment for an SOA signed IN-APP (SOAForms.tsx signs both parties directly on soa_forms, so soa-public-sign never runs for it). |
| `soa-public-sign` | `…/functions/v1/soa-public-sign` | POST | User JWT (Bearer) |  | Public endpoint — no JWT required, uses token-based auth |
| `soa-send-for-signature` | `…/functions/v1/soa-send-for-signature` | POST | User JWT (Bearer) |  | Authenticate user |
| `subaccount-email-stats` | `…/functions/v1/subaccount-email-stats` | POST | User JWT (Bearer) |  | User-scoped client for data queries |
| `submit-website-lead` | `…/functions/v1/submit-website-lead` | POST | User JWT (Bearer) |  | submit-website-lead — public (verify_jwt=false) endpoint for lead_form submissions on published websites. The owning subaccount/user is resolved server-side from the |
| `summarize-conversation` | `…/functions/v1/summarize-conversation` | POST | User JWT (Bearer) |  | Format messages for the AI |
| `support-chat` | `…/functions/v1/support-chat` | POST | User JWT (Bearer) |  | Screen-specific context based on current page |
| `support-preflight-scan` | `…/functions/v1/support-preflight-scan` | POST | User JWT (Bearer) |  | Proactive pre-flight scan for the unLocked AI support widget. Returns a small array of "issues" the user almost certainly wants to know |
| `support-resolution-embed` | `…/functions/v1/support-resolution-embed` | POST | User JWT (Bearer) |  | Embeds a resolved support ticket or chat into support_resolution_kb as canonical training material for future answers. Idempotent on (source_kind, source_id). |
| `sync-ad-accounts` | `…/functions/v1/sync-ad-accounts` | POST | User JWT (Bearer) |  | Get authenticated user |
| `sync-calendar` | `…/functions/v1/sync-calendar` | POST | User JWT (Bearer) |  | TOKEN REFRESH FUNCTIONS |
| `sync-contacts` | `…/functions/v1/sync-contacts` | POST | User JWT (Bearer) |  | Create admin client for decrypting tokens |
| `sync-facebook-forms` | `…/functions/v1/sync-facebook-forms` | POST | User JWT (Bearer) |  | DEPRECATED — SCHEDULED FOR DELETION. Do not build on this function. This is the first-generation Facebook lead-form sync, superseded by `meta-forms` |
| `sync-google-contacts` | `…/functions/v1/sync-google-contacts` | POST | User JWT (Bearer) |  | Google Contacts IMPORTER (Google → CRM) Pulls *all* of the connected Google account's contacts via the People API: |
| `sync-licensing-by-npn` | `…/functions/v1/sync-licensing-by-npn` | POST | User JWT (Bearer) |  | AWS NIPR Proxy configuration |
| `sync-outlook-contacts` | `…/functions/v1/sync-outlook-contacts` | POST | User JWT (Bearer) |  | Outlook (Microsoft Graph) Contacts IMPORTER (Outlook → CRM) Mirrors `sync-google-contacts` for Microsoft 365 / Outlook.com accounts. |
| `sync-pages` | `…/functions/v1/sync-pages` | POST | User JWT (Bearer) |  | DEPRECATED for provider 'meta'. Removal checklist at the bottom of this header. This function has zero callers — it exists only as an entry in supabase/config.toml — and its |
| `sync-signup-to-ghl` | `…/functions/v1/sync-signup-to-ghl` | POST | User JWT (Bearer) |  | ── Atomic deduplication guard ──────────────────────────────────────────── claim_ghl_sync atomically sets ghl_synced=TRUE and returns TRUE only if |
| `sync-stripe-invoices` | `…/functions/v1/sync-stripe-invoices` | POST | Provider webhook signature |  | Accept subaccount_id from request body for scoped wallet lookups |
| `system-threshold-monitor` | `…/functions/v1/system-threshold-monitor` | POST | User JWT (Bearer) | ✓ | Auth: cron secret or JWT |
| `teams-meeting-create` | `…/functions/v1/teams-meeting-create` | POST | User JWT (Bearer) |  | Refresh Microsoft access token |
| `teams-meeting-delete` | `…/functions/v1/teams-meeting-delete` | POST | User JWT (Bearer) |  | Refresh Microsoft access token |
| `teams-meeting-update` | `…/functions/v1/teams-meeting-update` | POST | User JWT (Bearer) |  | Refresh Microsoft access token |
| `test-advanced-support-slack` | `…/functions/v1/test-advanced-support-slack` | POST | User JWT (Bearer) |  | Internal notification email template (to team) - Light blue branded |
| `test-cancellation-drip` | `…/functions/v1/test-cancellation-drip` | POST | User JWT (Bearer) |  | ... template helpers (same as production) |
| `test-checkout-emails` | `…/functions/v1/test-checkout-emails` | POST | User JWT (Bearer) |  | Test Checkout Emails function. |
| `test-resend-email` | `…/functions/v1/test-resend-email` | POST | User JWT (Bearer) |  | unLocked CRM branded email templates Primary blue: #4A9EFF (hsl 213 100% 68%) |
| `test-send-email` | `…/functions/v1/test-send-email` | POST | User JWT (Bearer) |  | Fallback to env variables if database settings not available |
| `tiktok-backfill-leads` | `…/functions/v1/tiktok-backfill-leads` | POST | User JWT (Bearer) |  | TikTok Historical Lead Backfill Edge Function Pulls historical leads from TikTok API for forms that may have missed webhook deliveries |
| `tiktok-forms` | `…/functions/v1/tiktok-forms` | POST | User JWT (Bearer) |  | TikTok Lead Forms Edge Function Fetches lead generation forms from TikTok Ads API |
| `tiktok-manual-token` | `…/functions/v1/tiktok-manual-token` | POST | User JWT (Bearer) |  | Get authenticated user |
| `tiktok-map-fields` | `…/functions/v1/tiktok-map-fields` | POST | User JWT (Bearer) |  | TikTok Map Fields Edge Function Saves field mappings between TikTok lead form fields and CRM fields |
| `tiktok-poll-leads` | `…/functions/v1/tiktok-poll-leads` | POST | User JWT (Bearer) |  | TikTok Poll Leads Edge Function ARCHITECTURE DOCUMENTATION (FIX 7: Internal Alignment) |
| `tiktok-refresh-tokens` | `…/functions/v1/tiktok-refresh-tokens` | POST | User JWT (Bearer) |  | TikTok Refresh Tokens Edge Function Background job to refresh expiring TikTok OAuth tokens |
| `tiktok-retry-leads` | `…/functions/v1/tiktok-retry-leads` | POST | User JWT (Bearer) |  | TikTok Retry Leads Edge Function Background job to retry failed lead processing |
| `tiktok-subscribe-webhook` | `…/functions/v1/tiktok-subscribe-webhook` | POST | Provider webhook signature |  | TikTok Subscribe Webhook Edge Function Subscribes to TikTok Lead Ads webhook notifications for forms |
| `tiktok-sync-forms` | `…/functions/v1/tiktok-sync-forms` | POST | User JWT (Bearer) |  | TikTok Sync Forms Edge Function Background job to sync ad accounts nightly |
| `tiktok-webhook` | `…/functions/v1/tiktok-webhook` | GET, HEAD, POST | Provider webhook signature |  | TikTok Webhook Edge Function Receives lead notifications from TikTok Lead Ads |
| `track-quote-open` | `…/functions/v1/track-quote-open` | POST | User JWT (Bearer) |  | Public open-tracking endpoint for quote emails. Returns a 1x1 transparent GIF and records an open event in `quote_opens`. Designed to be loaded as |
| `transcribe-agent-ai-call` | `…/functions/v1/transcribe-agent-ai-call` | POST | User JWT (Bearer) |  | Process base64 in chunks to prevent memory issues |
| `transcribe-call` | `…/functions/v1/transcribe-call` | POST | User JWT (Bearer) |  | Process base64 in chunks to prevent memory issues |
| `transcribe-voice` | `…/functions/v1/transcribe-voice` | POST | User JWT (Bearer) |  | Transcribe audio using Wispr Flow REST API Expects base64-encoded 16kHz PCM WAV audio |
| `underwriting-chat` | `…/functions/v1/underwriting-chat` | POST | User JWT (Bearer) |  | Render ITK's real carrier read as a compact, model-readable block. Kept terse so it grounds the reply without dominating the prompt. The aggregator (ITK / |
| `unenroll-contact` | `…/functions/v1/unenroll-contact` | POST | User JWT (Bearer) |  | User-invoked unenrollment of a contact from a workflow (Automation -> Enrollment). The removal logic itself already existed, but only as the `remove_from_workflow` |
| `update-auth-email` | `…/functions/v1/update-auth-email` | POST | User JWT (Bearer) |  | Verify the caller is authenticated |
| `update-wallet-settings` | `…/functions/v1/update-wallet-settings` | POST | User JWT (Bearer) |  | Authenticate user |
| `validate-phone` | `…/functions/v1/validate-phone` | POST | User JWT (Bearer) |  | Resolve who is calling, for api_usage_logs attribution. config.toml sets verify_jwt = true for this function, so a user JWT is always |
| `verify-admin-access` | `…/functions/v1/verify-admin-access` | POST | User JWT (Bearer) |  | Verify Admin Access Edge Function SECURITY: Admin-only endpoint with restricted CORS |
| `verify-mailgun-domain` | `…/functions/v1/verify-mailgun-domain` | POST | Provider webhook signature |  | NOTE: wildcard CORS (same as add-mailgun-domain). This endpoint is JWT-verified and carries no cookie credentials, so `*` is safe — and it is the only way white-label |
| `verify-recaptcha` | `…/functions/v1/verify-recaptcha` | GET, POST | User JWT (Bearer) |  | Google reCAPTCHA v2 verification + site-key delivery. Routes: |
| `webhook-emit` | `…/functions/v1/webhook-emit` | POST | Provider webhook signature | ✓ | webhook-emit — internal helper that fans out a single webhook event to all subscribed `api_webhook_subscriptions` rows for a subaccount, signs each |
| `weekly-activity-digest` | `…/functions/v1/weekly-activity-digest` | POST | User JWT (Bearer) |  | Weekly Activity Digest function. |

### Email & Notifications (71)

| Function | Path | Methods | Auth | Cron | Description |
|---|---|---|---|---|---|
| `gmail-send-email` | `…/functions/v1/gmail-send-email` | POST | User JWT (Bearer) |  | ENFORCEMENT: Check DND status before sending email |
| `gmail-sync` | `…/functions/v1/gmail-sync` | POST | User JWT (Bearer) |  | trigger-workflow requires a valid userId. Subaccount-scoped email_accounts rows can have a null user_id, so we validate before firing the customer_replied bridge. |
| `mailgun-stats` | `…/functions/v1/mailgun-stats` | POST | User JWT (Bearer) |  | Handle CORS preflight |
| `mailgun-webhook` | `…/functions/v1/mailgun-webhook` | POST | Provider webhook signature |  | Rate limiting map (IP -> { count, resetTime }) |
| `notify-800-number` | `…/functions/v1/notify-800-number` | POST | User JWT (Bearer) |  | Slack notifications for 800 number request lifecycle events. |
| `notify-agency-new-signup` | `…/functions/v1/notify-agency-new-signup` | POST | User JWT (Bearer) | ✓ | Agency admin emails to notify |
| `notify-agency-past-due-resolved` | `…/functions/v1/notify-agency-past-due-resolved` | POST | User JWT (Bearer) |  | Notify Agency Past Due Resolved function. |
| `notify-agency-reactivation` | `…/functions/v1/notify-agency-reactivation` | POST | User JWT (Bearer) |  | Notify Agency Reactivation function. |
| `notify-agency-upgrade` | `…/functions/v1/notify-agency-upgrade` | POST | User JWT (Bearer) |  | Agency admin emails to notify — mirrors notify-agency-new-signup |
| `notify-ai-onboarding-completed` | `…/functions/v1/notify-ai-onboarding-completed` | POST | User JWT (Bearer) |  | Notify Ai Onboarding Completed function. |
| `notify-cancellation` | `…/functions/v1/notify-cancellation` | POST | User JWT (Bearer) |  | True when this fires because the user added their goodbye note on the final step, after the cancellation was already reported. Staff still need the note, |
| `notify-onboarding-completed` | `…/functions/v1/notify-onboarding-completed` | POST | User JWT (Bearer) |  | Best-effort display name from auth user_metadata, explicitly preferring first + last name. |
| `notify-slack-support` | `…/functions/v1/notify-slack-support` | POST | User JWT (Bearer) |  | Handle CORS preflight requests |
| `outlook-backfill-details` | `…/functions/v1/outlook-backfill-details` | POST | User JWT (Bearer) |  | One-time Outlook backfill — repair blank synced appointments. Outlook's /me/events/delta only re-emits CHANGED events, so resetting the |
| `outlook-delta-sync` | `…/functions/v1/outlook-delta-sync` | POST | User JWT (Bearer) |  | Outlook Delta Sync Edge Function Uses Microsoft Graph delta queries for robust incremental synchronization |
| `outlook-list-calendars` | `…/functions/v1/outlook-list-calendars` | POST | User JWT (Bearer) |  | Outlook List Calendars Edge Function Lists all calendars from user's Outlook account via Microsoft Graph API |
| `outlook-mail-sync` | `…/functions/v1/outlook-mail-sync` | POST | User JWT (Bearer) |  | Outlook (Microsoft Graph) Mail Sync — mirrors gmail-sync, writes to email_messages / email_threads. Invoked by frontend hook (useEmailThreads) after Outlook is connected, just like gmail-sync. |
| `outlook-refresh-token` | `…/functions/v1/outlook-refresh-token` | POST | User JWT (Bearer) |  | Outlook Refresh Token Edge Function Refreshes expired Outlook OAuth access tokens using refresh token |
| `outlook-renew-subscriptions` | `…/functions/v1/outlook-renew-subscriptions` | POST | User JWT (Bearer) |  | Outlook Renew Subscriptions Edge Function Renews Microsoft Graph webhook subscriptions before they expire |
| `outlook-save-calendar-selection` | `…/functions/v1/outlook-save-calendar-selection` | POST | User JWT (Bearer) |  | Outlook Save Calendar Selection Edge Function Saves user's selection of which Outlook calendars to sync |
| `outlook-subscribe-webhook` | `…/functions/v1/outlook-subscribe-webhook` | POST | Provider webhook signature |  | Outlook Subscribe Webhook Function Creates Microsoft Graph webhook subscriptions for calendar change notifications. |
| `outlook-webhook` | `…/functions/v1/outlook-webhook` | POST | Provider webhook signature |  | Outlook Webhook Edge Function Handles incoming webhook notifications from Microsoft Graph |
| `process-email-campaign-retries` | `…/functions/v1/process-email-campaign-retries` | POST | User JWT (Bearer) | ✓ | A throttled campaign finishes HERE, not in send-email-campaign (which skips its notification while sends are deferred) — so notify the owner |
| `process-single-email-queue` | `…/functions/v1/process-single-email-queue` | POST | User JWT (Bearer) | ✓ | Process Single Email Queue function. |
| `send-2fa-code` | `…/functions/v1/send-2fa-code` | POST | User JWT (Bearer) |  | Email 2FA Code Generator & Sender Actions: |
| `send-a2p-request-emails` | `…/functions/v1/send-a2p-request-emails` | POST | User JWT (Bearer) |  | Authenticate the user — only CRM users can submit A2P requests |
| `send-a2p-status-update` | `…/functions/v1/send-a2p-status-update` | POST | User JWT (Bearer) |  | Send A2p Status Update function. |
| `send-activation-email` | `…/functions/v1/send-activation-email` | POST | User JWT (Bearer) |  | Send Activation Email function. |
| `send-activity-summary` | `…/functions/v1/send-activity-summary` | POST | User JWT (Bearer) |  | Send Activity Summary function. |
| `send-admin-update-email` | `…/functions/v1/send-admin-update-email` | POST | User JWT (Bearer) |  | Get the update |
| `send-affiliate-payout-notification` | `…/functions/v1/send-affiliate-payout-notification` | POST | User JWT (Bearer) |  | Build payment method info if provided |
| `send-affiliate-signup-notification` | `…/functions/v1/send-affiliate-signup-notification` | POST | User JWT (Bearer) | ✓ | unLocked CRM branded affiliate signup notification email template |
| `send-appointment-reminders` | `…/functions/v1/send-appointment-reminders` | POST | User JWT (Bearer) |  | Phone normalization now handled by shared ensureE164 utility |
| `send-attribution-notification` | `…/functions/v1/send-attribution-notification` | POST | User JWT (Bearer) |  | Get user profile |
| `send-auth-email` | `…/functions/v1/send-auth-email` | POST | User JWT (Bearer) |  | Email templates for different auth actions |
| `send-booking-notification` | `…/functions/v1/send-booking-notification` | POST | User JWT (Bearer) |  | Notification settings for a booking that has no booking_link_id — Agent AI and portal bookings go straight through atomic_book_appointment and never |
| `send-build-idea` | `…/functions/v1/send-build-idea` | POST | User JWT (Bearer) |  | Send Build Idea function. |
| `send-clinic-invite` | `…/functions/v1/send-clinic-invite` | POST | User JWT (Bearer) |  | --- Ad-hoc in-memory rate limit (mirror of send-portal-invite) -------------- |
| `send-communication` | `…/functions/v1/send-communication` | POST | User JWT (Bearer) |  | Persist Gmail's thread truth immediately after a successful send, so replies can thread without waiting for gmail-sync (which may never run for all-outbound threads). |
| `send-crm-notification` | `…/functions/v1/send-crm-notification` | POST | User JWT (Bearer) |  | Placeholder token used by infoCard/ctaButton so that brandedTemplate can swap in the resolved branding.primaryColor at render-time. |
| `send-data-purchase-confirmation` | `…/functions/v1/send-data-purchase-confirmation` | POST | User JWT (Bearer) |  | Send email via Resend API |
| `send-email-campaign` | `…/functions/v1/send-email-campaign` | POST | User JWT (Bearer) |  | Attachment schema. `storagePath` points into the private `email-attachments` bucket and is read with the service-role client at send time; `url` is the |
| `send-email-reminders` | `…/functions/v1/send-email-reminders` | POST | User JWT (Bearer) |  | Automated Email Reminder Scheduler Sends email reminders at: |
| `send-feature-nudges` | `…/functions/v1/send-feature-nudges` | POST | User JWT (Bearer) |  | Weekly cron function: sends one "Have you tried X?" notification per user for features they haven't used yet. Auto-hides when they try the feature. |
| `send-feedback-email` | `…/functions/v1/send-feedback-email` | POST | User JWT (Bearer) |  | Send Feedback Email function. |
| `send-form-notification` | `…/functions/v1/send-form-notification` | POST | User JWT (Bearer) |  | Client confirmation settings |
| `send-integration-request` | `…/functions/v1/send-integration-request` | POST | User JWT (Bearer) |  | Send Integration Request function. |
| `send-invite-accepted` | `…/functions/v1/send-invite-accepted` | POST | User JWT (Bearer) |  | Get the team member details |
| `send-license-expiration-reminders` | `…/functions/v1/send-license-expiration-reminders` | POST | User JWT (Bearer) |  | ─── Helpers ──────────────────────────────────────────────────────────────── |
| `send-mailgun` | `…/functions/v1/send-mailgun` | POST | Provider webhook signature |  | MICROSOFT TOKEN REFRESH |
| `send-max-confirmation` | `…/functions/v1/send-max-confirmation` | POST | User JWT (Bearer) |  | Send Max Confirmation function. |
| `send-mention-notification` | `…/functions/v1/send-mention-notification` | POST | User JWT (Bearer) |  | Verify the caller |
| `send-new-user-notification` | `…/functions/v1/send-new-user-notification` | POST | User JWT (Bearer) |  | Authenticate the caller |
| `send-notification-test` | `…/functions/v1/send-notification-test` | POST | User JWT (Bearer) |  | Send Notification Test function. |
| `send-onboarding-email` | `…/functions/v1/send-onboarding-email` | POST | User JWT (Bearer) |  | ── Test-all path (no dedup) ────────────────────────────────────────────── |
| `send-password-reset` | `…/functions/v1/send-password-reset` | POST | User JWT (Bearer) |  | Create Supabase admin client to generate password reset link |
| `send-portal-invite` | `…/functions/v1/send-portal-invite` | POST | User JWT (Bearer) |  | --- Ad-hoc in-memory rate limit --------------------------------------------- NOTE: Backend has no shared rate-limit primitive; this is best-effort per |
| `send-pro-confirmation` | `…/functions/v1/send-pro-confirmation` | POST | User JWT (Bearer) |  | Send email via Resend API |
| `send-prospector-confirmation` | `…/functions/v1/send-prospector-confirmation` | POST | User JWT (Bearer) |  | Send email via Resend API |
| `send-quote-to-contact` | `…/functions/v1/send-quote-to-contact` | POST | User JWT (Bearer) |  | Sends a quote to a contact via email and/or SMS, with a generated PDF "Quote Summary" attachment. Logs a single combined activity to |
| `send-sms` | `…/functions/v1/send-sms` | POST | User JWT (Bearer) |  | Outbound SMS sender with Agency-Level A2P Support: - Subaccount isolation: Only uses phones owned by the sending subaccount |
| `send-smtp-email` | `…/functions/v1/send-smtp-email` | POST | User JWT (Bearer) |  | Decrypt SMTP password using the shared encryption utilities |
| `send-subaccount-invitation` | `…/functions/v1/send-subaccount-invitation` | POST | User JWT (Bearer) |  | Send via Mailgun |
| `send-support-notification` | `…/functions/v1/send-support-notification` | POST | User JWT (Bearer) |  | Support ticket notifications go ONLY to this hardcoded allow-list. Do NOT derive recipients from user_roles, workspace owners, submitters, |
| `send-system-alert` | `…/functions/v1/send-system-alert` | POST | User JWT (Bearer) |  | Handle CORS preflight |
| `send-team-invite` | `…/functions/v1/send-team-invite` | POST | User JWT (Bearer) |  | Send Team Invite Edge Function PURPOSE: |
| `send-tiktok-event` | `…/functions/v1/send-tiktok-event` | POST | User JWT (Bearer) |  | SHA-256 hash function for PII data (required by TikTok Events API) TikTok requires email and phone to be lowercase, trimmed, and SHA-256 hashed |
| `send-welcome-email` | `…/functions/v1/send-welcome-email` | POST | User JWT (Bearer) |  | Send Welcome Email function. |
| `send-whatsapp` | `…/functions/v1/send-whatsapp` | POST | User JWT (Bearer) |  | Secure Twilio WhatsApp sender with DND enforcement SECURITY: Restricted CORS + server-side subaccount validation |
| `send-whitelabel-request` | `…/functions/v1/send-whitelabel-request` | POST | User JWT (Bearer) |  | "Book a 15-minute kickoff call" CTA in the White Label confirmation email. Kept in step with the same buttons on the White Label settings page — both are |

### Integrations & Webhooks (53)

| Function | Path | Methods | Auth | Cron | Description |
|---|---|---|---|---|---|
| `calendly-backfill` | `…/functions/v1/calendly-backfill` | POST | Provider webhook signature |  | One-time importer: pulls the caller's existing Calendly meetings (past N months plus everything upcoming) into the appointments table. Safe to re-run: events |
| `calendly-event-types` | `…/functions/v1/calendly-event-types` | POST | Provider webhook signature |  | Get ALL Calendly connections for the subaccount (not just current user) |
| `calendly-poll-sync` | `…/functions/v1/calendly-poll-sync` | POST | Provider webhook signature | ✓ | Scheduled Calendly sync for connections that have no webhook. Calendly gates webhook subscriptions behind its Standard/Teams/Enterprise plans, so |
| `calendly-subscribe-webhook` | `…/functions/v1/calendly-subscribe-webhook` | POST | Provider webhook signature |  | Get Calendly connection |
| `calendly-webhook` | `…/functions/v1/calendly-webhook` | POST | Provider webhook signature |  | Verify Calendly webhook signature using HMAC SHA-256 |
| `comtrack-auto-sync` | `…/functions/v1/comtrack-auto-sync` | POST | Provider webhook signature |  | Commission+ Auto-Sync — scheduled background function Iterates through all active Commission+ connections with auto_sync_enabled = true |
| `comtrack-sync` | `…/functions/v1/comtrack-sync` | POST | Provider webhook signature |  | Commission+ reference endpoint. Both values were wrong and both were verified by direct request (2026-08-17): |
| `comtrack-webhook` | `…/functions/v1/comtrack-webhook` | POST | Provider webhook signature |  | Commission+ Inbound Webhook Receives push updates from Commission+ when: |
| `facebook-webhook` | `…/functions/v1/facebook-webhook` | GET, POST | User JWT (Bearer) |  | ⚠️ DEPRECATED — DO NOT USE This is the legacy single-tenant Facebook webhook handler. |
| `ghl-import-manager` | `…/functions/v1/ghl-import-manager` | POST | Provider webhook signature |  | Ghl Import Manager function. |
| `ghl-import-resume` | `…/functions/v1/ghl-import-resume` | POST | Provider webhook signature |  | Cron job: runs every 2 minutes to resume stalled/queued GHL import chunks. |
| `ghl-import-worker` | `…/functions/v1/ghl-import-worker` | POST | Provider webhook signature |  | ─── Auth: Only allow service-to-service calls ─── |
| `google-ads-attach-webhook` | `…/functions/v1/google-ads-attach-webhook` | POST | Provider webhook signature |  | Google Ads Attach Webhook function. |
| `google-ads-lead-webhook` | `…/functions/v1/google-ads-lead-webhook` | POST | Provider webhook signature |  | Constant-time key comparison to prevent timing attacks |
| `google-ads-list-accounts` | `…/functions/v1/google-ads-list-accounts` | POST | User JWT (Bearer) |  | Google Ads List Accounts function. |
| `google-ads-list-lead-forms` | `…/functions/v1/google-ads-list-lead-forms` | POST | User JWT (Bearer) |  | CRM webhook URL substring used to detect "our" webhook on a lead form |
| `google-ads-save-account` | `…/functions/v1/google-ads-save-account` | POST | User JWT (Bearer) |  | Google Ads Save Account function. |
| `google-calendar-webhook` | `…/functions/v1/google-calendar-webhook` | GET, POST | Provider webhook signature |  | Token refresh helper |
| `google-list-calendars` | `…/functions/v1/google-list-calendars` | POST | User JWT (Bearer) |  | Parse body to get subaccountId |
| `google-meet-create` | `…/functions/v1/google-meet-create` | POST | User JWT (Bearer) |  | Refresh Google access token |
| `google-renew-subscriptions` | `…/functions/v1/google-renew-subscriptions` | POST | User JWT (Bearer) |  | Renews Google Calendar push notification subscriptions before they expire Should run daily via cron to ensure continuous real-time sync |
| `google-save-calendar-selection` | `…/functions/v1/google-save-calendar-selection` | POST | User JWT (Bearer) |  | Upsert calendar selections - first delete existing for this user/provider/subaccount, then insert This handles the subaccount_id in the unique constraint properly |
| `google-sheets-action` | `…/functions/v1/google-sheets-action` | POST | User JWT (Bearer) |  | Column mappings for create/update |
| `google-sheets-get-headers` | `…/functions/v1/google-sheets-get-headers` | POST | User JWT (Bearer) |  | Get first row (headers) from the worksheet |
| `google-sheets-list-drives` | `…/functions/v1/google-sheets-list-drives` | POST | User JWT (Bearer) |  | Check if token is expired |
| `google-sheets-list-spreadsheets` | `…/functions/v1/google-sheets-list-spreadsheets` | POST | User JWT (Bearer) |  | List Google Sheets in the specified drive |
| `google-sheets-list-worksheets` | `…/functions/v1/google-sheets-list-worksheets` | POST | User JWT (Bearer) |  | Get spreadsheet metadata including worksheets |
| `google-sheets-oauth-callback` | `…/functions/v1/google-sheets-oauth-callback` | POST | User JWT (Bearer) |  | Verify HMAC signature on state |
| `google-sheets-oauth-init` | `…/functions/v1/google-sheets-oauth-init` | POST | User JWT (Bearer) |  | Get authenticated user |
| `google-subscribe-calendar` | `…/functions/v1/google-subscribe-calendar` | POST | User JWT (Bearer) |  | Token refresh helper |
| `healthsherpa-push` | `…/functions/v1/healthsherpa-push` | POST | User JWT (Bearer) |  | HealthSherpa push. Supports two products: |
| `healthsherpa-save-settings` | `…/functions/v1/healthsherpa-save-settings` | POST | User JWT (Bearer) |  | Secure endpoint for saving HealthSherpa settings (Phase 4 hardened). Secrets are stored encrypted at rest via DB trigger (pgcrypto + vault). |
| `healthsherpa-webhook` | `…/functions/v1/healthsherpa-webhook` | POST | Provider webhook signature |  | HealthSherpa inbound webhook. HealthSherpa delivers ONE event per Medicare submission, shaped |
| `meta-check-permissions` | `…/functions/v1/meta-check-permissions` | POST | Provider webhook signature |  | Capability → scope mapping comes from _shared/meta-oauth-scopes.ts so it cannot drift from what oauth-init actually asks Facebook for. |
| `meta-connections` | `…/functions/v1/meta-connections` | POST | Provider webhook signature |  | Get authenticated user |
| `meta-disconnect` | `…/functions/v1/meta-disconnect` | POST | Provider webhook signature |  | Get Meta account |
| `meta-fetch-insights` | `…/functions/v1/meta-fetch-insights` | POST | Provider webhook signature |  | Get Meta account |
| `meta-forms` | `…/functions/v1/meta-forms` | POST | Provider webhook signature |  | Parse request body for subaccountId and mode |
| `meta-map-fields` | `…/functions/v1/meta-map-fields` | POST | Provider webhook signature |  | Get user's profile to get subaccount_id |
| `meta-refresh-tokens` | `…/functions/v1/meta-refresh-tokens` | POST | Provider webhook signature | ✓ | Renews Meta long-lived user tokens before they expire (~60 days). This function was dead twice over until 2026-08-11, and that is the reason Meta customers |
| `meta-reset-permissions` | `…/functions/v1/meta-reset-permissions` | POST | Provider webhook signature |  | Explicit "Reset Facebook Page permissions" escape hatch — DELETE /me/permissions. Facebook keeps a per-app, per-Facebook-user grant of which Pages we may see, and the OAuth |
| `meta-retry-leads` | `…/functions/v1/meta-retry-leads` | POST | Provider webhook signature | ✓ | Statuses worth another attempt. 'completed' is done and 'skipped_duplicate' is a legitimate outcome rather than a failure, so neither is ever re-attempted. |
| `meta-select-page` | `…/functions/v1/meta-select-page` | POST | Provider webhook signature |  | Get Meta account |
| `meta-send-message` | `…/functions/v1/meta-send-message` | POST | Provider webhook signature |  | Get channel (includes subaccount_id for isolation) |
| `meta-subscribe-webhook` | `…/functions/v1/meta-subscribe-webhook` | POST | Provider webhook signature |  | Get Meta channel with page access token |
| `meta-sync-assets` | `…/functions/v1/meta-sync-assets` | POST | Provider webhook signature |  | Re-reads the Pages, Instagram accounts and ad accounts for a connected Meta account and refreshes the cached copies in meta_accounts / meta_channels. Backs the "Refresh Pages" |
| `meta-webhook` | `…/functions/v1/meta-webhook` | GET, POST | Provider webhook signature |  | Verify Meta webhook signature. Env var notes (canonical names): |
| `zoom-create-meeting` | `…/functions/v1/zoom-create-meeting` | POST | Provider webhook signature |  | Refresh Zoom access token |
| `zoom-delete-meeting` | `…/functions/v1/zoom-delete-meeting` | POST | Provider webhook signature |  | Refresh Zoom access token |
| `zoom-disconnect` | `…/functions/v1/zoom-disconnect` | POST | Provider webhook signature |  | Helper: return a structured failure (success: false) with secure headers. |
| `zoom-refresh-tokens` | `…/functions/v1/zoom-refresh-tokens` | POST | Provider webhook signature |  | Refresh Zoom access token |
| `zoom-update-meeting` | `…/functions/v1/zoom-update-meeting` | POST | Provider webhook signature |  | Refresh Zoom access token |
| `zoom-webhook` | `…/functions/v1/zoom-webhook` | GET, POST | Provider webhook signature |  | Decrypt OAuth token |

### Quoting & Enrollment (29)

| Function | Path | Methods | Auth | Cron | Description |
|---|---|---|---|---|---|
| `aca-doc-extract` | `…/functions/v1/aca-doc-extract` | POST | User JWT (Bearer) |  | aca-doc-extract — vision-based document auto-fill for ACA quoting/application. Accepts a base64 image/PDF (driver's license, pay stub, insurance card, etc.) |
| `aca-eligibility-check` | `…/functions/v1/aca-eligibility-check` | POST | User JWT (Bearer) |  | For creating new lead |
| `aca-plan-summary` | `…/functions/v1/aca-plan-summary` | POST | User JWT (Bearer) |  | Aca Plan Summary function. |
| `aca-public-quote` | `…/functions/v1/aca-public-quote` | POST | None (public) |  | Subaccount behind the public link — needed to file the quote. |
| `aca-quote` | `…/functions/v1/aca-quote` | POST | User JWT (Bearer) |  | aca-quote — AGENT marketplace quoting (verify_jwt handled in code). Authentication and response shaping only. The quote itself comes from |
| `aca-quote-ai` | `…/functions/v1/aca-quote-ai` | POST | User JWT (Bearer) |  | Aca Quote Ai function. |
| `aca-self-enroll` | `…/functions/v1/aca-self-enroll` | POST | User JWT (Bearer) |  | Where the lead came from, as a tag on the Contacts page. Keyed by the `source` written to the lead row so the two can't drift apart. |
| `compulife-quote` | `…/functions/v1/compulife-quote` | POST | User JWT (Bearer) |  | compulife-quote — Life insurance quoting via Compulife AWS proxy REQUIRED SUPABASE SECRETS (set in Dashboard → Settings → Edge Functions): |
| `csg-dvh-quote` | `…/functions/v1/csg-dvh-quote` | POST | User JWT (Bearer) |  | New API parameters |
| `csg-eapp` | `…/functions/v1/csg-eapp` | POST | User JWT (Bearer) |  | CSG E-App — enrollment application management. Docs: https://enrollmentplatform.docs.apiary.io/ (see docs/csg-eapp/SCOPING.md) |
| `csg-eapp-probe` | `…/functions/v1/csg-eapp-probe` | POST | User JWT (Bearer) |  | CSG E-App access probe — uses documented header (x-api-token) and endpoints per https://enrollmentplatform.docs.apiary.io/ |
| `csg-eapp-sync` | `…/functions/v1/csg-eapp-sync` | POST | User JWT (Bearer) | ✓ | Derive our status string from CSG's boolean flags (most-advanced wins). |
| `csg-hi-quote` | `…/functions/v1/csg-hi-quote` | POST | User JWT (Bearer) |  | In-memory fallback for same instance; primary cache is in csg_token_cache table. |
| `csg-ma-quote` | `…/functions/v1/csg-ma-quote` | POST | User JWT (Bearer) |  | Drugs the client is taking — passed to CSG as rxcui[] so per-plan tier copays populate. CSG returns concrete dollar copays for each of the 5 standard Part D tiers per plan |
| `csg-medigap-quote` | `…/functions/v1/csg-medigap-quote` | POST | User JWT (Bearer) |  | Service-role callers only: the tenant whose rate-limit budget this call spends. |
| `dvh-plan-explain` | `…/functions/v1/dvh-plan-explain` | POST | User JWT (Bearer) |  | Dvh Plan Explain function. |
| `dvh-quote-ai` | `…/functions/v1/dvh-quote-ai` | POST | User JWT (Bearer) |  | Dvh Quote Ai function. |
| `hi-quote-ai` | `…/functions/v1/hi-quote-ai` | POST | User JWT (Bearer) |  | Rate limiting |
| `ixn-quotes` | `…/functions/v1/ixn-quotes` | POST | User JWT (Bearer) |  | IXN error payloads we have seen embed: "referenceId: <uuid>" in the message. |
| `ixnQuoteTest` | `…/functions/v1/ixnQuoteTest` | POST | User JWT (Bearer) |  | Initialize Supabase for auth validation |
| `life-compulife-quote-ai` | `…/functions/v1/life-compulife-quote-ai` | POST | User JWT (Bearer) |  | Life Compulife Quote Ai function. |
| `life-public-quote` | `…/functions/v1/life-public-quote` | POST | None (public) |  | life-public-quote — PUBLIC (verify_jwt = false) Powers the consumer life quote widget at /q/:slug ("Beacon" phase 1). |
| `ma-plan-explain` | `…/functions/v1/ma-plan-explain` | POST | User JWT (Bearer) |  | A missing value means the carrier did not report it — say so explicitly, and never let downstream math treat it as $0. |
| `ma-quote-ai` | `…/functions/v1/ma-quote-ai` | POST | User JWT (Bearer) |  | Valid US state codes |
| `medigap-quote-ai` | `…/functions/v1/medigap-quote-ai` | POST | User JWT (Bearer) |  | Rate limiting |
| `private-plans-api` | `…/functions/v1/private-plans-api` | POST | User JWT (Bearer) |  | ==================== Types ==================== |
| `private-plans-quote-ai` | `…/functions/v1/private-plans-quote-ai` | POST | User JWT (Bearer) |  | Private Plans Quote Ai function. |
| `private-plans-search` | `…/functions/v1/private-plans-search` | POST | User JWT (Bearer) |  | ==================== Types ==================== |
| `quote-ai` | `…/functions/v1/quote-ai` | POST | User JWT (Bearer) |  | RATE LIMITING - In-memory fast check |

### Telephony & Messaging (31)

| Function | Path | Methods | Auth | Cron | Description |
|---|---|---|---|---|---|
| `a2p-auto-approve` | `…/functions/v1/a2p-auto-approve` | POST | User JWT (Bearer) |  | A2p Auto Approve function. |
| `a2p-register` | `…/functions/v1/a2p-register` | POST | User JWT (Bearer) |  | Helper to make Twilio API calls |
| `make-voice-call` | `…/functions/v1/make-voice-call` | POST | User JWT (Bearer) |  | Outbound Voice Call with GHL-style features: - DND check before calling |
| `phone-system-alerts` | `…/functions/v1/phone-system-alerts` | POST | User JWT (Bearer) | ✓ | Agency admin emails to notify |
| `twilio-a2p-registration` | `…/functions/v1/twilio-a2p-registration` | POST | Provider webhook signature |  | Get authenticated user |
| `twilio-call-queue` | `…/functions/v1/twilio-call-queue` | POST | Provider webhook signature |  | Twilio Call Queue Handler SECURITY: Validates X-Twilio-Signature to prevent spoofed queue requests. |
| `twilio-caller-id` | `…/functions/v1/twilio-caller-id` | POST | User JWT (Bearer) |  | Initialize Supabase with user's auth |
| `twilio-campaign-chime` | `…/functions/v1/twilio-campaign-chime` | POST | Provider webhook signature |  | Validate Twilio signature |
| `twilio-conference-manage` | `…/functions/v1/twilio-conference-manage` | POST | Provider webhook signature |  | Create a conference record in the database. The actual Twilio Conference is created when the first participant joins via TwiML. |
| `twilio-conference-status` | `…/functions/v1/twilio-conference-status` | POST | Provider webhook signature |  | Terminal call_conferences statuses that must never be revived or overwritten. |
| `twilio-dial-complete` | `…/functions/v1/twilio-dial-complete` | POST | Provider webhook signature |  | Twilio <Dial> action handler — terminates the parent call when the browser <Client> leg ends. |
| `twilio-end-call` | `…/functions/v1/twilio-end-call` | POST | User JWT (Bearer) |  | End/Hang-up a Twilio Call Uses Twilio's Update Call API to terminate an in-progress call. |
| `twilio-hold-call` | `…/functions/v1/twilio-hold-call` | POST | User JWT (Bearer) |  | Hold music options |
| `twilio-inbound-sms` | `…/functions/v1/twilio-inbound-sms` | POST | Provider webhook signature |  | Twilio Inbound SMS Webhook Handler SECURITY: Validates X-Twilio-Signature to prevent spoofed inbound messages. |
| `twilio-incoming-call` | `…/functions/v1/twilio-incoming-call` | POST | Provider webhook signature |  | Twilio Incoming Call Webhook Handler SECURITY: Validates X-Twilio-Signature to prevent spoofed webhook attacks. |
| `twilio-phone-numbers` | `…/functions/v1/twilio-phone-numbers` | POST | Provider webhook signature |  | Twilio Phone Number Management Handles search, purchase (with correct webhook configuration), and release |
| `twilio-ring-group` | `…/functions/v1/twilio-ring-group` | POST | Provider webhook signature |  | Twilio Ring Group Handler SECURITY: Validates X-Twilio-Signature to prevent spoofed routing requests. |
| `twilio-sms-status` | `…/functions/v1/twilio-sms-status` | POST | Provider webhook signature |  | Twilio SMS Status Webhook Handler SECURITY: Validates X-Twilio-Signature to prevent spoofed status updates. |
| `twilio-transfer-call` | `…/functions/v1/twilio-transfer-call` | POST | Provider webhook signature |  | Twilio Transfer Call function. |
| `twilio-trusthub-callback` | `…/functions/v1/twilio-trusthub-callback` | POST | Provider webhook signature |  | Initialize Supabase client |
| `twilio-voice-app-status` | `…/functions/v1/twilio-voice-app-status` | POST | User JWT (Bearer) |  | This endpoint is safe to be auth-protected so it can't be used as a Twilio probe. |
| `twilio-voice-status` | `…/functions/v1/twilio-voice-status` | POST | Provider webhook signature |  | Twilio Voice Status Webhook Handler SECURITY: Validates X-Twilio-Signature to prevent spoofed status callbacks. |
| `twilio-voice-token` | `…/functions/v1/twilio-voice-token` | POST | Provider webhook signature |  | Generate Twilio Access Token for browser-based calling Manual JWT creation following Twilio's exact specification |
| `twilio-voice-twiml` | `…/functions/v1/twilio-voice-twiml` | POST | Provider webhook signature |  | TwiML endpoint for browser-based voice calls (Twilio Client SDK) SECURITY: Validates X-Twilio-Signature to prevent spoofed requests |
| `twilio-voicemail` | `…/functions/v1/twilio-voicemail` | POST | Provider webhook signature |  | Twilio Voicemail Handler SECURITY: Validates X-Twilio-Signature to prevent spoofed voicemail requests. |
| `twilio-voicemail-complete` | `…/functions/v1/twilio-voicemail-complete` | POST | Provider webhook signature |  | Twilio Voicemail Complete Handler SECURITY: Validates X-Twilio-Signature to prevent spoofed recording callbacks. |
| `twilio-voicemail-drop` | `…/functions/v1/twilio-voicemail-drop` | POST | Provider webhook signature |  | Resolve CORS headers per-request so the preview, app.unlockedcrm.ai, and crm.awakeningfg.com origins all work (not just the first allowed origin). |
| `twilio-voicemail-transcription` | `…/functions/v1/twilio-voicemail-transcription` | POST | Provider webhook signature |  | Twilio Voicemail Transcription Handler Called by Twilio when voicemail transcription is complete. |
| `twilio-whisper` | `…/functions/v1/twilio-whisper` | POST | Provider webhook signature |  | Twilio Whisper Handler - Press 1 to Accept SECURITY: Validates X-Twilio-Signature to prevent spoofed whisper requests. |
| `twilio-whisper-result` | `…/functions/v1/twilio-whisper-result` | POST | Provider webhook signature |  | Twilio Whisper Result Handler SECURITY: Validates X-Twilio-Signature to prevent spoofed DTMF results. |
| `voicemail-proxy` | `…/functions/v1/voicemail-proxy` | HEAD, POST | User JWT (Bearer) |  | Voicemail Proxy - Serves voicemail audio files with correct Content-Type headers This edge function proxies audio files from Supabase Storage, ensuring |

## Conventions & limits

- **Invocation:** the app calls functions via `supabase.functions.invoke('<name>', { body })` — always an HTTPS `POST` with a JSON body to `https://gzigyepfasiumngxilai.supabase.co/functions/v1/<name>`.
- **Rate limit:** 100 req/min per key on the Public API. Internal functions are not publicly rate-limited but enforce auth.
- **CORS:** functions answer `OPTIONS` preflights; browser-facing functions use a whitelist of app origins.
- **Errors:** `400` validation, `401` missing/invalid credentials, `403` permission denied, `404` not found, `429` rate limited (Public API), `500` internal.
- **Counts:** 538 edge functions total; 35 cron-triggered; 85 webhook receivers; 1 public REST endpoint (`/public-api`) with 4 methods.
