Developers

FunnelGenie API

A REST API over everything your workspace does: contacts, funnels, CRM, orders, courses, communities, affiliates, email, and webhooks.

OpenAPI 3.0 specification ↗

Authentication

Create an API key in Settings → Developers and send it on every request:

curl https://your-app.com/api/v1/contacts \
  -H "Authorization: Bearer fg_live_xxxxxxxxxx_…"

Keys carry scopes; each endpoint below names the scope it requires. Requests are always scoped to the key's workspace.

Errors and request IDs

Errors share one shape, and every response carries an X-Request-Id header for support:

{ "error": { "code": "insufficient_scope", "message": "…", "request_id": "req_…" } }

Pagination

List endpoints take limit (1–100, default 25) and cursor, and return next_cursor — pass it back to fetch the next page; null means the end.

Rate limits

120 requests per minute per API key. Beyond that, requests return 429 rate_limited — back off and retry.

Idempotency

Send an Idempotency-Key header (any unique string up to 255 chars) on POST requests you may retry. For 24 hours, repeating the same request with the same key replays the original response (marked Idempotency-Replay: true) instead of performing the operation twice. Reusing a key for a different request returns 409 idempotency_key_reuse.

Webhook signatures

Webhook deliveries are signed: X-FunnelGenie-Signature: t=<timestamp>,v1=<hex>, where v1 = HMAC-SHA256(secret, timestamp + "." + body). Verify the signature and reject stale timestamps. Failed deliveries retry with backoff for up to 6 attempts.

Contacts

GET/api/v1/contacts

List contacts

Requires the `contacts:read` scope.

Parameters

  • limit (query) — Page size.
  • cursor (query) — The `next_cursor` from the previous page.
POST/api/v1/contacts

Create (or upsert) a contact

Requires the `contacts:write` scope.

Supports Idempotency-Key.

Request body

  • email (string, required)
  • first_name (string)
  • last_name (string)
  • phone (string)
  • funnel_id (string) — Attach the contact to this funnel as a lead.
  • tags (array)
GET/api/v1/contacts/{id}

Get a contact

Requires the `contacts:read` scope.

Parameters

  • id (path, required) — Contact id
PATCH/api/v1/contacts/{id}

Update a contact

Requires the `contacts:write` scope.

Parameters

  • id (path, required) — Contact id

Request body

  • first_name (string)
  • last_name (string)
  • phone (string)
  • tags (array)

Funnels

GET/api/v1/funnels

List funnels

Requires the `funnels:read` scope.

Parameters

  • limit (query) — Page size.
  • cursor (query) — The `next_cursor` from the previous page.
GET/api/v1/funnels/{id}

Get a funnel with its steps

Requires the `funnels:read` scope.

Parameters

  • id (path, required) — Funnel id
POST/api/v1/funnels/{id}/clone

Clone a funnel

Requires the `funnels:write` scope. Duplicates the funnel inside the workspace via the portable exporter — secrets, customer data, and experiments never travel with the copy.

Parameters

  • id (path, required) — Funnel id
Supports Idempotency-Key.

CRM

GET/api/v1/pipelines

List pipelines with their stages

Requires the `opportunities:read` scope.

GET/api/v1/opportunities

List opportunities

Requires the `opportunities:read` scope.

Parameters

  • limit (query) — Page size.
  • cursor (query) — The `next_cursor` from the previous page.
POST/api/v1/opportunities

Create an opportunity

Requires the `opportunities:write` scope. Provide `contact_id`, or `email` to find-or-create the contact.

Supports Idempotency-Key.

Request body

  • title (string, required)
  • contact_id (string)
  • email (string)
  • value_cents (integer)
  • currency (string) — 3-letter code
  • pipeline_id (string)
  • stage_id (string)
  • source (string)
  • expected_close_at (string) — ISO 8601 datetime
PATCH/api/v1/opportunities/{id}

Update or move an opportunity

Requires the `opportunities:write` scope.

Parameters

  • id (path, required) — Opportunity id

Request body

  • title (string)
  • value_cents (integer)
  • stage_id (string) — Moving stages logs a stage-change activity.
  • status (OPEN | WON | LOST)
  • lost_reason (string)
  • expected_close_at (string) — ISO 8601 datetime, or null

Orders

GET/api/v1/orders

List orders

Requires the `orders:read` scope.

Parameters

  • limit (query) — Page size.
  • cursor (query) — The `next_cursor` from the previous page.
GET/api/v1/orders/{id}

Get an order

Requires the `orders:read` scope.

Parameters

  • id (path, required) — Order id

Courses

GET/api/v1/courses

List courses

Requires the `courses:read` scope.

Parameters

  • limit (query) — Page size.
  • cursor (query) — The `next_cursor` from the previous page.
GET/api/v1/courses/{id}

Get a course with its curriculum

Requires the `courses:read` scope.

Parameters

  • id (path, required) — Course id
GET/api/v1/courses/{id}/enrollments

List a course's enrollments

Requires the `courses:read` scope.

Parameters

  • id (path, required) — Course id
  • limit (query) — Page size.
  • cursor (query) — The `next_cursor` from the previous page.
POST/api/v1/courses/{id}/enrollments

Enroll a contact in a course

Requires the `enrollments:write` scope. Provide `contact_id` or `email`. Re-enrolling a revoked contact re-activates them.

Parameters

  • id (path, required) — Course id
Supports Idempotency-Key.

Request body

  • contact_id (string)
  • email (string)
  • send_login_email (boolean) — Also email the member a portal sign-in link.

Communities

GET/api/v1/communities

List communities

Requires the `communities:read` scope.

Parameters

  • limit (query) — Page size.
  • cursor (query) — The `next_cursor` from the previous page.
POST/api/v1/communities/{id}/members

Add a contact to a community

Requires the `communities:write` scope. Banned members are refused (403) — lift bans from the dashboard.

Parameters

  • id (path, required) — Community id
Supports Idempotency-Key.

Request body

  • email (string, required)
  • first_name (string)
  • last_name (string)
  • role (MEMBER | MODERATOR)

Affiliates

GET/api/v1/affiliates

List affiliates

Requires the `affiliates:read` scope.

Parameters

  • limit (query) — Page size.
  • cursor (query) — The `next_cursor` from the previous page.
  • program_id (query)
  • status (query)
POST/api/v1/affiliates

Register an affiliate into a program

Requires the `affiliates:write` scope. Idempotent per (program, email). Set `approve: true` to skip the approval queue.

Supports Idempotency-Key.

Request body

  • program_id (string, required)
  • email (string, required)
  • first_name (string)
  • last_name (string)
  • paypal_email (string)
  • approve (boolean)

Email

POST/api/v1/emails

Send a marketing email to a contact

Requires the `email:send` scope. Sends through the compliance path: suppression list, plan cap, unsubscribe footer and List-Unsubscribe header are always enforced. Suppressed addresses return 409; plan caps return 402.

Supports Idempotency-Key.

Request body

  • to (string, required)
  • subject (string, required)
  • html (string, required) — HTML body
  • text (string) — Plain-text alternative

Webhooks

GET/api/v1/webhooks

List webhook endpoints

Requires the `webhooks:manage` scope.

Parameters

  • limit (query) — Page size.
  • cursor (query) — The `next_cursor` from the previous page.
POST/api/v1/webhooks

Register a webhook endpoint

Requires the `webhooks:manage` scope. The signing secret is returned in the response. Deliveries carry `X-FunnelGenie-Signature: t=<timestamp>,v1=<HMAC-SHA256(secret, timestamp.body)>` and retry with backoff for up to 6 attempts. Omit `events` to subscribe to everything.

Supports Idempotency-Key.

Request body

  • url (string, required)
  • events (array) — Event types to subscribe to (empty = all).
  • description (string)
DELETE/api/v1/webhooks/{id}

Delete a webhook endpoint

Requires the `webhooks:manage` scope.

Parameters

  • id (path, required) — Webhook endpoint id

Webhook event catalog, delivery logs, and key management live in your dashboard under Settings → Developers.