Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.elasticfunnels.io/llms.txt

Use this file to discover all available pages before exploring further.

List All Products

Retrieve all products for a project with pagination.
brand
string
required
The brand/project ID
page
number
Page number for pagination (default: 1)
per_page
number
Number of results per page (default: 25)
Request
GET /api/brands/{brand}/products
cURL
curl https://app.elasticfunnels.io/api/brands/{brand_id}/products \
  -H "EF-Access-Key: your_api_key_here"
{
  "current_page": 1,
  "data": [
    {
      "id": 2,
      "brand_id": 1,
      "code": "glucotil",
      "type": "physical",
      "title": "1 Bottle",
      "checkout_title": null,
      "price": 69,
      "retail_price": 99,
      "image": "https://storage.googleapis.com/asper-digital/1/1-bottle.png",
      "image_link": "https://storage.googleapis.com/asper-digital/1/1-bottle.png",
      "units": 1,
      "sku": "prod1",
      "classification": "main",
      "product_files": [],
      "unit_cost": null,
      "unit_weight_oz": null,
      "fulfillment_cost": null,
      "packaging_cost": null,
      "fuel_surcharge_cost": null,
      "cogs": null,
      "custom_attributes": null,
      "merchant_product_ids": [],
      "physical_units_per_product": null,
      "fulfillment_multiply_sku": 0,
      "sku_category": null,
      "sku_subcategory": null,
      "product_specifications": null,
      "shipping_profile_id": null,
      "is_subscription": false,
      "subscription_frequency": null,
      "subscription_frequency_unit": null,
      "subscription_trial_days": null,
      "subscription_first_charge_free": false,
      "average_shipping_cost": null,
      "bonuses": []
    }
  ],
  "first_page_url": "https://app.elasticfunnels.io/api/brands/1/products?page=1",
  "from": 1,
  "last_page": 1,
  "last_page_url": "https://app.elasticfunnels.io/api/brands/1/products?page=1",
  "links": [
    {
      "url": null,
      "label": "« Previous",
      "active": false
    },
    {
      "url": "https://app.elasticfunnels.io/api/brands/1/products?page=1",
      "label": "1",
      "active": true
    },
    {
      "url": null,
      "label": "Next »",
      "active": false
    }
  ],
  "next_page_url": null,
  "path": "https://app.elasticfunnels.io/api/brands/1/products",
  "per_page": 25,
  "prev_page_url": null,
  "to": 8,
  "total": 8
}

List All Products (Unpaginated)

Get all products without pagination for dropdown lists.
brand
string
required
The brand/project ID
Request
GET /api/brands/{brand}/products/all
cURL
curl https://app.elasticfunnels.io/api/brands/{brand_id}/products/all \
  -H "EF-Access-Key: your_api_key_here"

Get Product Details

Retrieve details about a specific product.
brand
string
required
The brand/project ID
product
string
required
The product ID
Request
GET /api/brands/{brand}/products/{product}
cURL
curl https://app.elasticfunnels.io/api/brands/{brand_id}/products/2 \
  -H "EF-Access-Key: your_api_key_here"
{
  "id": 2,
  "brand_id": 1,
  "code": "glucotil",
  "type": "physical",
  "title": "1 Bottle",
  "checkout_title": null,
  "price": 69,
  "retail_price": 99,
  "image": "https://storage.googleapis.com/asper-digital/1/1-bottle.png",
  "image_link": "https://storage.googleapis.com/asper-digital/1/1-bottle.png",
  "units": 1,
  "sku": "prod1",
  "classification": "main",
  "product_files": [],
  "unit_cost": null,
  "unit_weight_oz": null,
  "fulfillment_cost": null,
  "packaging_cost": null,
  "fuel_surcharge_cost": null,
  "cogs": null,
  "custom_attributes": null,
  "merchant_product_ids": {},
  "physical_units_per_product": null,
  "fulfillment_multiply_sku": 0,
  "sku_category": null,
  "sku_subcategory": null,
  "product_specifications": null,
  "shipping_profile_id": null,
  "is_subscription": false,
  "subscription_frequency": null,
  "subscription_frequency_unit": null,
  "subscription_trial_days": null,
  "subscription_first_charge_free": false,
  "average_shipping_cost": null,
  "bonuses": []
}

Product Fields Reference

  • code - Unique product code/identifier
  • title - Product display name
  • checkout_title - Alternative title for checkout (optional)
  • type - Product type: physical, digital
  • classification - Product classification: main, upsell, downsell, bump, bonus
  • price - Selling price (in currency units)
  • retail_price - Suggested retail/original price
  • units - Number of units included
  • sku - Stock Keeping Unit identifier
  • unit_cost - Cost per unit
  • unit_weight_oz - Weight per unit in ounces
  • fulfillment_cost - Cost to fulfill the order
  • packaging_cost - Packaging cost
  • fuel_surcharge_cost - Fuel surcharge
  • cogs - Cost of Goods Sold
  • physical_units_per_product - Physical units per product
  • fulfillment_multiply_sku - Multiply fulfillment by SKU quantity
  • average_shipping_cost - Average shipping cost
  • image - Product image URL
  • image_link - Full URL to product image
  • product_files - Array of downloadable files attached to the product
  • is_subscription - Whether this is a subscription product
  • subscription_frequency - Billing frequency (e.g., 1, 2, 3)
  • subscription_frequency_unit - Unit: day, week, month, year
  • subscription_trial_days - Number of trial days
  • subscription_first_charge_free - Whether first charge is free
  • custom_attributes - Array of custom key-value pairs
  • merchant_product_ids - Object mapping merchant names to product IDs
  • product_specifications - Array of product specifications
  • shipping_profile_id - Associated shipping profile
  • sku_category - SKU category
  • sku_subcategory - SKU subcategory
  • bonuses - Array of bonus products associated with this product

Create Product

Create a new product.
brand
string
required
The brand/project ID
code
string
required
Unique product code
title
string
required
Product title
price
number
required
Product price
type
string
required
Product type: physical or digital
classification
string
required
Classification: main, upsell, downsell, bump, or bonus
retail_price
number
Retail/original price
units
number
Number of units
sku
string
Stock Keeping Unit
image
string
Product image URL
is_subscription
boolean
Whether this is a subscription product
subscription_frequency
number
Billing frequency (required if is_subscription is true)
subscription_frequency_unit
string
Frequency unit: day, week, month, year
Request
POST /api/brands/{brand}/products
cURL
curl -X POST https://app.elasticfunnels.io/api/brands/{brand_id}/products \
  -H "EF-Access-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "product_123",
    "title": "Premium Product",
    "price": 49.99,
    "retail_price": 79.99,
    "type": "physical",
    "classification": "main",
    "units": 1,
    "sku": "PREM-001"
  }'

Subscription Product Example

cURL
curl -X POST https://app.elasticfunnels.io/api/brands/{brand_id}/products \
  -H "EF-Access-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "monthly_subscription",
    "title": "Monthly Subscription",
    "price": 29.99,
    "type": "physical",
    "classification": "main",
    "is_subscription": true,
    "subscription_frequency": 1,
    "subscription_frequency_unit": "month",
    "subscription_trial_days": 14,
    "subscription_first_charge_free": true
  }'

Update Product

Update an existing product.
brand
string
required
The brand/project ID
product
string
required
The product ID
Request
PUT /api/brands/{brand}/products/{product}
cURL
curl -X PUT https://app.elasticfunnels.io/api/brands/{brand_id}/products/{product_id} \
  -H "EF-Access-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated Product Name",
    "price": 59.99
  }'

Delete Product

Delete a product.
brand
string
required
The brand/project ID
product
string
required
The product ID
Request
DELETE /api/brands/{brand}/products/{product}
cURL
curl -X DELETE https://app.elasticfunnels.io/api/brands/{brand_id}/products/{product_id} \
  -H "EF-Access-Key: your_api_key_here"

Clone Product

Create a copy of an existing product.
brand
string
required
The brand/project ID
product
string
required
The product ID to clone
Request
POST /api/brands/{brand}/products/{product}/clone
cURL
curl -X POST https://app.elasticfunnels.io/api/brands/{brand_id}/products/2/clone \
  -H "EF-Access-Key: your_api_key_here"

Product Classifications

ClassificationDescriptionUsage
mainMain product offerPrimary product in funnel
upsellUpsell productOffered after initial purchase
downsellDownsell productOffered if upsell is declined
bumpOrder bumpCheckbox add-on at checkout
bonusBonus productFree gift or bonus item

Product Bonuses

Products can have associated bonus products. The bonuses array contains bonus product relationships:
{
  "bonuses": [
    {
      "bonus_product_id": 23,
      "product_id": 3,
      "brand_id": 1
    },
    {
      "bonus_product_id": 24,
      "product_id": 3,
      "brand_id": 1
    }
  ]
}
When a customer purchases a product with bonuses, they automatically receive the bonus products.

Downloadable Files

Digital downloads and bonus downloads are stored in product_files. Each file row can include:
  • purpose - digital or bonus
  • title - Optional display title
  • description - Optional description shown in customer-facing download UIs
  • image - Optional thumbnail/cover image URL for this file
  • file - File URL
  • kind - Coarse classification derived from the file extension and metadata.mime_type. One of audio, video, document, image, archive, file. Lets clients branch on file type without re-parsing the URL.
  • is_primary - Marks the default file for that purpose
  • sort_order - Controls display order
  • metadata - Public file metadata. Only the following fields are exposed:
    • mime_type - MIME type of the file (e.g. "audio/mpeg", "application/pdf")
    • size - Size in bytes
    • checksum - Optional checksum recorded at upload (may be null)
    • extension - Lowercase extension without the dot (e.g. "pdf", "mp3"). Derived from the file URL when possible, with a small mime-type fallback for opaque/signed URLs. Empty string when neither source can produce one.
    Internal storage pointers (provider, storage_path, brand_file_id) are intentionally not returned.
{
  "product_files": [
    {
      "purpose": "digital",
      "title": "Quick Start Guide",
      "description": "PDF onboarding guide",
      "image": "https://cdn.example.com/guide-cover.jpg",
      "file": "https://cdn.example.com/guide.pdf",
      "kind": "document",
      "is_primary": true,
      "sort_order": 0,
      "metadata": {
        "mime_type": "application/pdf",
        "size": 182734,
        "checksum": null,
        "extension": "pdf"
      }
    },
    {
      "purpose": "bonus",
      "title": "Bonus Audio",
      "file": "https://cdn.example.com/bonus.mp3",
      "kind": "audio",
      "is_primary": true,
      "sort_order": 0,
      "metadata": {
        "mime_type": "audio/mpeg",
        "size": 10876045,
        "checksum": null,
        "extension": "mp3"
      }
    }
  ]
}
Use bonus-product relationships for entitlement, and use product_files for the actual downloadable assets those products expose.

Custom Attributes

Products support custom key-value attributes for flexibility:
{
  "custom_attributes": [
    {
      "key": "download",
      "value": "https://example.com/download"
    },
    {
      "key": "access_code",
      "value": "ABC123"
    }
  ]
}
Common uses:
  • Download links for digital products
  • Access codes for member areas
  • Special instructions
  • Custom tracking parameters

Merchant Product IDs

Map your ElasticFunnels products to merchant platform product IDs:
{
  "merchant_product_ids": {
    "buygoods": "1234",
    "clickbank": "PROD-001",
    "stripe": "prod_abc123"
  }
}

Subscription Tiers

Products can have tiered subscription billing — different prices at different intervals (e.g. monthly then annually). Pass subscription_tiers as an array in the Create or Update body.
is_subscription
boolean
Mark product as a subscription product
subscription_frequency
number
Default billing interval count (e.g. 1 for every-1-month)
subscription_frequency_unit
string
day, week, month, or year
subscription_trial_days
number
Free trial length in days (min: 0)
subscription_first_charge_free
boolean
Waive the first billing charge
subscription_tiers
array
Array of tier objects. When provided, overrides the flat subscription_frequency / subscription_frequency_unit values.
subscription_tiers[].interval
string
required
day, week, month, or year
subscription_tiers[].interval_count
number
required
How many units of interval between charges (min: 1)
subscription_tiers[].price
number
required
Billing amount for this tier (min: 0)
subscription_tiers[].tier
string
Optional tier label (max 64 chars)
subscription_tiers[].label
string
Display label shown to the customer (max 255 chars)
subscribe_save_discount_percent
number
Discount shown as “subscribe & save” (0–100%)
Subscription tiers example
{
  "is_subscription": true,
  "subscription_trial_days": 14,
  "subscribe_save_discount_percent": 15,
  "subscription_tiers": [
    {
      "tier": "monthly",
      "interval": "month",
      "interval_count": 1,
      "price": 29.99,
      "label": "Monthly — $29.99/mo"
    },
    {
      "tier": "annual",
      "interval": "year",
      "interval_count": 1,
      "price": 249.00,
      "label": "Annual — $249/yr (save 30%)"
    }
  ]
}

Product Variants & Options

Products can have variants (e.g. size/colour combinations). Variants are managed inline via the product_fields and variants arrays on Create/Update.

Product Fields (variant dimensions)

product_fields defines the variant dimensions (e.g. “Size”, “Colour”):
{
  "product_fields": [
    { "name": "Size",   "type": "select", "options": ["S", "M", "L", "XL"], "position": 0 },
    { "name": "Colour", "type": "select", "options": ["Red", "Blue"],        "position": 1 }
  ]
}

Variants

Each variant is a combination of field values with an optional per-variant price and SKU:
{
  "variants": [
    { "option1": "S",  "option2": "Red",  "code": "SKU-S-RED",  "price": 29.99 },
    { "option1": "M",  "option2": "Red",  "code": "SKU-M-RED",  "price": 29.99 },
    { "option1": "L",  "option2": "Blue", "code": "SKU-L-BLUE", "price": 34.99 }
  ]
}
variants[].id
number
Existing variant ID for update (omit to create new)
variants[].code
string
Variant SKU/code (max 128 chars)
variants[].option1
string
Value for the first product field (max 128 chars)
variants[].option2
string
Value for the second product field (max 128 chars)
variants[].option3
string
Value for the third product field (max 128 chars)
variants[].price
number
Override price for this variant (null = use product base price)
variants[].image
string
Variant image URL (max 512 chars)
variants[].currency
string
3-letter ISO currency code (e.g. USD)

Variant Options

Variant options are brand-level reusable option sets (e.g. “Shoe Sizes”, “Colours”). They can be attached to multiple products.

List Variant Options

GET /api/brands/{brand}/variant-options

Get All Variant Options (unpaginated)

GET /api/brands/{brand}/variant-options/all

Create Variant Option

POST /api/brands/{brand}/variant-options
name
string
required
Option set name (e.g. Shirt Sizes)
values
array
required
Array of option value strings (e.g. ["XS", "S", "M", "L", "XL"])
cURL
curl -X POST https://app.elasticfunnels.io/api/brands/{brand_id}/variant-options \
  -H "EF-Access-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"name": "Shirt Sizes", "values": ["XS", "S", "M", "L", "XL"]}'

Update Variant Option

PUT /api/brands/{brand}/variant-options/{variant_option}

Delete Variant Option

DELETE /api/brands/{brand}/variant-options/{variant_option}

Product Categories

Organise products into a two-level category hierarchy (category → subcategory).

List Categories

GET /api/brands/{brand}/product-categories

Get All Categories (unpaginated)

GET /api/brands/{brand}/product-categories/all

Create Category

POST /api/brands/{brand}/product-categories
name
string
required
Category name
parent_id
number
Parent category ID — omit for top-level categories, provide for subcategories.
cURL — create top-level category
curl -X POST https://app.elasticfunnels.io/api/brands/{brand_id}/product-categories \
  -H "EF-Access-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"name": "Supplements"}'
cURL — create subcategory
curl -X POST https://app.elasticfunnels.io/api/brands/{brand_id}/product-categories \
  -H "EF-Access-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"name": "Weight Loss", "parent_id": 3}'
{
  "id": 4,
  "name": "Weight Loss",
  "parent_id": 3,
  "brand_id": 42,
  "created_at": "2024-12-11T10:00:00.000000Z"
}

Update Category

PUT /api/brands/{brand}/product-categories/{product_category}

Delete Category

DELETE /api/brands/{brand}/product-categories/{product_category}
When creating a product, product_category_id must be a top-level category (no parent_id). To assign a subcategory, also provide product_subcategory_id (which must belong to the category). Providing a subcategory without a category returns a 422.

Coupons

Create and manage discount codes for products.

List Coupons

GET /api/brands/{brand}/coupons
per_page
number
Results per page (max 100, default: 25)

Get Coupon

GET /api/brands/{brand}/coupons/{coupon}

Create Coupon

POST /api/brands/{brand}/coupons
code
string
required
Coupon code (max 64 chars). Must be unique per brand.
type
string
required
percent — percentage off, or fixed — fixed amount off
value
number
required
Discount value. For percent, clamped to 0–100 automatically.
name
string
Internal label (max 128 chars)
status
string
active (default), draft, or disabled
product_ids
array
Limit discount to specific product IDs. Empty/null means all products.
excluded_product_ids
array
Product IDs to exclude from the discount.
applies_on_bump
boolean
Whether the coupon applies to order bump products.
valid_from
string
ISO 8601 date — coupon becomes active from this date.
valid_until
string
ISO 8601 date — coupon expires after this date. Must be on or after valid_from.
usage_limit
number
Maximum number of redemptions (null = unlimited).
cURL — 20% off all products
curl -X POST https://app.elasticfunnels.io/api/brands/{brand_id}/coupons \
  -H "EF-Access-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "SAVE20",
    "name": "20% Off Launch Promo",
    "type": "percent",
    "value": 20,
    "status": "active",
    "valid_from": "2024-12-01",
    "valid_until": "2024-12-31",
    "usage_limit": 500
  }'
cURL — $10 off specific products
curl -X POST https://app.elasticfunnels.io/api/brands/{brand_id}/coupons \
  -H "EF-Access-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "BOTTLE10",
    "type": "fixed",
    "value": 10,
    "product_ids": [5, 6]
  }'
{
  "id": 12,
  "code": "SAVE20",
  "name": "20% Off Launch Promo",
  "type": "percent",
  "value": 20,
  "status": "active",
  "product_ids": null,
  "excluded_product_ids": null,
  "applies_on_bump": false,
  "valid_from": "2024-12-01",
  "valid_until": "2024-12-31",
  "usage_limit": 500,
  "brand_id": 42,
  "created_at": "2024-12-11T10:00:00.000000Z"
}

Update Coupon

PUT /api/brands/{brand}/coupons/{coupon}
All fields optional on update. Use this to disable an expired coupon:
cURL — disable coupon
curl -X PUT https://app.elasticfunnels.io/api/brands/{brand_id}/coupons/12 \
  -H "EF-Access-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"status": "disabled"}'

Delete Coupon

DELETE /api/brands/{brand}/coupons/{coupon}

Validate Coupon

Check if a coupon code is valid and get its details (useful for frontend validation before applying at checkout).
GET /api/brands/{brand}/coupons/validate?code=SAVE20
code
string
required
Coupon code to validate
{
  "valid": true,
  "coupon": {
    "id": 12,
    "code": "SAVE20",
    "type": "percent",
    "value": 20,
    "product_ids": null
  }
}

Notes

  • Product code must be unique within the brand
  • classification of bonus products are automatically included with their parent products
  • Subscription products require subscription_frequency and subscription_frequency_unit
  • All costs (COGS, fulfillment, packaging) are tracked for profit margin calculations
  • Images are returned as both image (relative path) and image_link (full URL)
  • Downloadable assets live in product_files, not top-level bonus_file / digital_file columns
    • product_category_id must be a root-level category; use product_subcategory_id for sub-level
    • Coupon type: "percent" values are clamped to 0–100 automatically
When updating products that are actively used in funnels, changes may affect existing customer orders and analytics.