Get Product Draft Variants
Retrieve a paginated list of variants on a product's unpublished overlay.
The list includes unpublished overlay variants that do not appear on
Get Product Variants. Archived overlay variants are omitted —
fetch one by ID at Get Product Draft Variant. When no
overlay exists, the list is the live projection — the same variants nested on
Get Product Draft. Each item uses the live
Product Variant shape — there is no
draft_version or preview_url on the item. See Status.
Filters and pagination match Get Product Variants.
Omitting sort leaves variants in overlay order. amount and name sort as on the live
list. created_at orders by when a variant was created, which a variant that exists only
on the overlay does not have yet: those sort last on created_at and first on
-created_at, keeping them together at one end of the list either way.
Request
GET /products/{productId}/draft/variants
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
productId | string | Yes | Product UUID |
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
page | integer | No | 1 | Page number for pagination |
per_page | integer | No | 10 | Items per page (min: 1, max: 100). |
sort | string | No | — | Sort order: created_at, amount, or name. Prefix with - for descending. |
type | string | No | — | Filter by variant type. One of one_time or recurring. |
is_hidden | boolean | No | — | Filter by checkout visibility. true returns only variants hidden from checkout; false returns only visible ones. Accepts true/false or 1/0. |
query | string | No | — | Search term. Partial, case-insensitive match on the variant name or custom_id. |
Omitting a filter or passing it empty means "no filter on that field". All filters combine
with AND. Passing a non-empty but unparseable value — an unknown sort field, an invalid
type, a non-boolean is_hidden, or an out-of-range per_page — returns a 400. The
query term is matched loosely and never returns a 400.
Every response includes the total in pagination.total. An out-of-range page
returns empty items and current_page set to that page. total and
total_pages still describe the full result set.
Example Request
curl -X GET "https://cart.easy.tools/api/v1/products/0632bef5-c308-42cd-9cba-89a7a4f722bb/draft/variants" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Response
Success Response (200)
Returns { items, pagination }. Unpublished overlay variants have checkout_url: null.
{
"items": [
{
"id": "d91c65aa-b221-4aa4-b626-cf0d8a198749",
"status": "published",
"type": "one_time",
"recurring_options": null,
"name": "250g Package",
"amount": 1999,
"currency": "usd",
"checkout_url": "https://cart.easy.tools/checkout/premium-coffee?plan=price_123",
"custom_id": "SKU-250G",
"is_hidden": false,
"trial_period_days": null,
"active_cycles": null,
"cancel_early": false,
"keep_access_after_expiring": false,
"allow_multiple_subscriptions": false,
"active_days": 365,
"quantity": 100,
"has_quantity": true,
"old_price": 29,
"active_from": "2026-01-01T00:00:00+00:00",
"active_until": "2026-12-31T23:59:59+00:00",
"access_until": null,
"show_active_until_counter": true,
"tax_behavior": "exclusive",
"refund_days": 14,
"redirect_url": "https://mysite.com/thank-you",
"redirect_time": 5,
"file": null,
"files": [],
"invoice_remarks": null,
"has_shipping": false,
"delivery_enabled": false,
"delivery_service": null,
"delivery_address_optional": true,
"delivery_options": null,
"shipping_phone_required": false,
"phone_tooltip": null,
"mandatory_consent": null,
"optional_consent": null,
"digital_consent": null,
"newsletter_consent": null,
"newsletter_consent_required": false,
"newsletter_discount": null,
"vat_rate": null,
"gtu_code": null,
"flat_rate": null,
"exempt_tax_kind": null,
"tax_category": null,
"dashboard_header": null,
"long_description": null,
"cta_text": null,
"cta_url": null,
"credits": null,
"show_net_price": false,
"pay_what_you_want": null,
"purchase_button_text": null,
"upsells": [],
"custom_fields": null
},
{
"id": "5272bfcf-4e92-458d-b513-80ca474a16e4",
"status": "published",
"type": "one_time",
"recurring_options": null,
"name": "100g Sample",
"amount": 999,
"currency": "usd",
"checkout_url": null,
"custom_id": null,
"is_hidden": false,
"trial_period_days": null,
"active_cycles": null,
"cancel_early": false,
"keep_access_after_expiring": false,
"allow_multiple_subscriptions": false,
"active_days": null,
"quantity": null,
"has_quantity": false,
"old_price": null,
"active_from": null,
"active_until": null,
"access_until": null,
"show_active_until_counter": null,
"tax_behavior": "exclusive",
"refund_days": null,
"redirect_url": null,
"redirect_time": null,
"file": null,
"files": [],
"invoice_remarks": null,
"has_shipping": false,
"delivery_enabled": false,
"delivery_service": null,
"delivery_address_optional": true,
"delivery_options": null,
"shipping_phone_required": false,
"phone_tooltip": null,
"mandatory_consent": null,
"optional_consent": null,
"digital_consent": null,
"newsletter_consent": null,
"newsletter_consent_required": false,
"newsletter_discount": null,
"vat_rate": null,
"gtu_code": null,
"flat_rate": null,
"exempt_tax_kind": null,
"tax_category": null,
"dashboard_header": null,
"long_description": null,
"cta_text": null,
"cta_url": null,
"credits": null,
"show_net_price": false,
"pay_what_you_want": null,
"purchase_button_text": null,
"upsells": [],
"custom_fields": null
}
],
"pagination": {
"current_page": 1,
"total_pages": 1,
"per_page": 10,
"total": 2
}
}
Each entry in items has the same shape as the response of
Get Product Variant. There is no
include on this list, so custom_fields stays null. Expand it on
Get Product Draft Variant.
Pagination Object
| Field | Type | Description |
|---|---|---|
current_page | integer | The requested page. May be greater than total_pages when items is empty. |
total_pages | integer | Total number of pages |
per_page | integer | Effective page size (echoes the per_page request parameter) |
total | integer | Total number of non-archived overlay variants for the product, across all pages |
Error Responses
Bad Request (400)
Returned when the product ID is invalid, per_page is out of range, sort names an unknown
field, type is not one_time or recurring, or is_hidden is not a boolean. The message
describes the problem.
{
"message": "Invalid product ID"
}
Product Not Found (404)
{
"message": "Product with ID 0632bef5-c308-42cd-9cba-89a7a4f722bb not found"
}