Products represent goods or services available for purchase. They serve as the catalog items that can be added to orders and included in subscription plans.

Pricing

All prices are stored in cents. For example, a $29.99 product has pricing.amount: 2999.

Security: When creating orders, the product price is always looked up from the database — not from the request. This prevents price manipulation.

POST /products

Create a product

Creates a new product in your catalog. Products can be used in orders (one-time purchases) and included in subscription plans (recurring).

SKU Rules

The sku must be unique per merchant. Use lowercase alphanumeric characters, hyphens, and underscores only (e.g., premium-coaching-12wk). If a duplicate SKU is submitted, a 409 Conflict is returned.

Pricing

All amounts are in cents. For example, a $29.99 product has pricing.amount: 2999.

Header parameters

NameTypeDescription
EPD-Version
string
API version override (format `YYYY-MM-DD`). If omitted, your account's pinned version or the latest version is used.
e.g. "2026-02-11"
X-EPD-Idempotency-Keyrequired
string (uuid)
UUID v4 idempotency key. Same key with same request returns cached response. Keys expire after 24 hours.
e.g. "550e8400-e29b-41d4-a716-446655440000"

Request body required

FieldTypeDescription
namerequired
string
Product name. HTML not allowed.
e.g. "Premium Coaching Program"
descriptionrequired
string
Product description. HTML not allowed.
e.g. "12-week intensive coaching program"
pricingrequired
object
amountrequired
integer
Price in cents.
e.g. 29700
currencyrequired
string
Three-letter ISO 4217 currency code (lowercase).
e.g. "usd"
requires_shippingrequired
boolean
Whether this product requires shipping.
e.g. false
skurequired
string
Unique stock keeping unit. Lowercase alphanumeric, hyphens, and underscores only.
e.g. "coaching_premium_12wk"
availability
enum
in_stockout_of_stockpreorder
e.g. "in_stock"
category
string
e.g. "Coaching"
brand
string
e.g. "Elite Academy"
material
string
e.g. "Cotton blend"
weight
string
e.g. "0.5 kg"
return_window
integer
Return window in days.
e.g. 30
inventory_quantity
integer
e.g. 150
metadata
Metadata

Code samples

curl -X POST https://api.epd.com/v1/products \
  -H "Authorization: Bearer epd_test_sk_xxxx" \
  -H "Content-Type: application/json" \
  -H "EPD-Version: 2026-02-11" \
  -H "X-EPD-Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "Premium Coaching Program",
    "description": "12-week intensive coaching program",
    "pricing": { "amount": 29700, "currency": "usd" },
    "requires_shipping": false,
    "sku": "coaching_premium_12wk"
  }'
const response = await fetch('https://api.epd.com/v1/products', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer epd_test_sk_xxxx',
    'Content-Type': 'application/json',
    'EPD-Version': '2026-02-11',
    'X-EPD-Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    name: 'Premium Coaching Program',
    description: '12-week intensive coaching program',
    pricing: { amount: 29700, currency: 'usd' },
    requires_shipping: false,
    sku: 'coaching_premium_12wk',
  }),
});

const product = await response.json();
console.log(product.id); // 6ba7b810-9dad-11d1-80b4-00c04fd430c8
import uuid
import requests

response = requests.post(
    'https://api.epd.com/v1/products',
    headers={
        'Authorization': 'Bearer epd_test_sk_xxxx',
        'EPD-Version': '2026-02-11',
        'X-EPD-Idempotency-Key': str(uuid.uuid4()),
    },
    json={
        'name': 'Premium Coaching Program',
        'description': '12-week intensive coaching program',
        'pricing': {'amount': 29700, 'currency': 'usd'},
        'requires_shipping': False,
        'sku': 'coaching_premium_12wk',
    }
)

product = response.json()
print(product['id'])  # 6ba7b810-9dad-11d1-80b4-00c04fd430c8

Responses

201 Product created.
FieldTypeDescription
idrequired
string
e.g. "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
namerequired
string
e.g. "Premium Coaching Program"
descriptionnullable
string
e.g. "12-week intensive coaching program"
pricingrequired
object
amountrequired
integer
Price in cents.
e.g. 29700
currencyrequired
string
Three-letter ISO 4217 currency code.
e.g. "usd"
requires_shippingrequired
boolean
e.g. false
skurequired
string
Unique stock keeping unit.
e.g. "coaching_premium_12wk"
availabilityrequired
enum
in_stockout_of_stockpreorder
e.g. "in_stock"
categorynullable
string
e.g. "Coaching"
brandnullable
string
e.g. "Elite Academy"
materialnullable
string
e.g. "Cotton blend"
weightnullable
string
e.g. "0.5 kg"
return_windownullable
integer
Return window in days (0-365).
e.g. 30
inventory_quantitynullable
integer
Available inventory count.
e.g. 150
images
array[ProductImage]
metadata
Metadata
activerequired
boolean
e.g. true
created_atrequired
string (date-time)
e.g. "2024-01-15T10:30:00.000Z"
updated_atrequired
string (date-time)
e.g. "2024-01-15T10:30:00.000Z"
400 Bad Request — The request was invalid or cannot be served.
FieldTypeDescription
errorrequired
object
typerequired
enum
The type of error.
invalid_request_errorauthentication_errorauthorization_errorrate_limit_erroridempotency_errorprocessing_errorwebhook_error
coderequired
string
A short string identifying the specific error.
e.g. "validation_error"
messagerequired
string
A human-readable message providing details about the error.
e.g. "Request validation failed"
paramnullable
string
The parameter that caused the error, if applicable.
e.g. "email"
request_id
string
Unique request identifier for debugging.
e.g. "req_a1b2c3d4e5f67890abcdef0123456789"
field_errors
array[object]
Detailed field-level errors for validation failures.
401 Unauthorized — Authentication failed.
FieldTypeDescription
errorrequired
object
typerequired
enum
The type of error.
invalid_request_errorauthentication_errorauthorization_errorrate_limit_erroridempotency_errorprocessing_errorwebhook_error
coderequired
string
A short string identifying the specific error.
e.g. "validation_error"
messagerequired
string
A human-readable message providing details about the error.
e.g. "Request validation failed"
paramnullable
string
The parameter that caused the error, if applicable.
e.g. "email"
request_id
string
Unique request identifier for debugging.
e.g. "req_a1b2c3d4e5f67890abcdef0123456789"
field_errors
array[object]
Detailed field-level errors for validation failures.
409 Conflict — The request conflicts with existing data.
FieldTypeDescription
errorrequired
object
typerequired
enum
The type of error.
invalid_request_errorauthentication_errorauthorization_errorrate_limit_erroridempotency_errorprocessing_errorwebhook_error
coderequired
string
A short string identifying the specific error.
e.g. "validation_error"
messagerequired
string
A human-readable message providing details about the error.
e.g. "Request validation failed"
paramnullable
string
The parameter that caused the error, if applicable.
e.g. "email"
request_id
string
Unique request identifier for debugging.
e.g. "req_a1b2c3d4e5f67890abcdef0123456789"
field_errors
array[object]
Detailed field-level errors for validation failures.
GET /products

List all products

Returns a paginated list of products.

Query parameters

NameTypeDescription
limit
integer
Number of items to return per page.
Default: 10
starting_after
string
Cursor for forward pagination. Returns items created after this ID.
e.g. "550e8400-e29b-41d4-a716-446655440000"
ending_before
string
Cursor for backward pagination. Returns items created before this ID.
e.g. "550e8400-e29b-41d4-a716-446655440001"
sort
string
Sort order. Format: `field[direction]` or `-field` for descending. Default: `created_at[desc]`.
e.g. "created_at[desc]"
active
boolean
Filter by active status.
e.g. true
expand
string
Expand related resources: `images`.
e.g. "images"
fields[products]
string
Sparse fieldsets — comma-separated list of fields to include (e.g., `id,name,pricing,created`).
e.g. "id,name,pricing,created"

Header parameters

NameTypeDescription
EPD-Version
string
API version override (format `YYYY-MM-DD`). If omitted, your account's pinned version or the latest version is used.
e.g. "2026-02-11"

Responses

200 A list of products.
FieldTypeDescription
data
array[Product]
url
any
e.g. "/v1/products"
401 Unauthorized — Authentication failed.
FieldTypeDescription
errorrequired
object
typerequired
enum
The type of error.
invalid_request_errorauthentication_errorauthorization_errorrate_limit_erroridempotency_errorprocessing_errorwebhook_error
coderequired
string
A short string identifying the specific error.
e.g. "validation_error"
messagerequired
string
A human-readable message providing details about the error.
e.g. "Request validation failed"
paramnullable
string
The parameter that caused the error, if applicable.
e.g. "email"
request_id
string
Unique request identifier for debugging.
e.g. "req_a1b2c3d4e5f67890abcdef0123456789"
field_errors
array[object]
Detailed field-level errors for validation failures.
GET /products/{id}

Retrieve a product

Path parameters

NameTypeDescription
idrequired
string
e.g. "6ba7b810-9dad-11d1-80b4-00c04fd430c8"

Query parameters

NameTypeDescription
expand
string
Expand related resources: `images`.

Header parameters

NameTypeDescription
EPD-Version
string
API version override (format `YYYY-MM-DD`). If omitted, your account's pinned version or the latest version is used.
e.g. "2026-02-11"

Responses

200 The product.
FieldTypeDescription
idrequired
string
e.g. "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
namerequired
string
e.g. "Premium Coaching Program"
descriptionnullable
string
e.g. "12-week intensive coaching program"
pricingrequired
object
amountrequired
integer
Price in cents.
e.g. 29700
currencyrequired
string
Three-letter ISO 4217 currency code.
e.g. "usd"
requires_shippingrequired
boolean
e.g. false
skurequired
string
Unique stock keeping unit.
e.g. "coaching_premium_12wk"
availabilityrequired
enum
in_stockout_of_stockpreorder
e.g. "in_stock"
categorynullable
string
e.g. "Coaching"
brandnullable
string
e.g. "Elite Academy"
materialnullable
string
e.g. "Cotton blend"
weightnullable
string
e.g. "0.5 kg"
return_windownullable
integer
Return window in days (0-365).
e.g. 30
inventory_quantitynullable
integer
Available inventory count.
e.g. 150
images
array[ProductImage]
metadata
Metadata
activerequired
boolean
e.g. true
created_atrequired
string (date-time)
e.g. "2024-01-15T10:30:00.000Z"
updated_atrequired
string (date-time)
e.g. "2024-01-15T10:30:00.000Z"
404 Not Found — The requested resource doesn't exist.
FieldTypeDescription
errorrequired
object
typerequired
enum
The type of error.
invalid_request_errorauthentication_errorauthorization_errorrate_limit_erroridempotency_errorprocessing_errorwebhook_error
coderequired
string
A short string identifying the specific error.
e.g. "validation_error"
messagerequired
string
A human-readable message providing details about the error.
e.g. "Request validation failed"
paramnullable
string
The parameter that caused the error, if applicable.
e.g. "email"
request_id
string
Unique request identifier for debugging.
e.g. "req_a1b2c3d4e5f67890abcdef0123456789"
field_errors
array[object]
Detailed field-level errors for validation failures.
PATCH /products/{id}

Update a product

Path parameters

NameTypeDescription
idrequired
string
e.g. "6ba7b810-9dad-11d1-80b4-00c04fd430c8"

Header parameters

NameTypeDescription
EPD-Version
string
API version override (format `YYYY-MM-DD`). If omitted, your account's pinned version or the latest version is used.
e.g. "2026-02-11"
X-EPD-Idempotency-Keyrequired
string (uuid)
UUID v4 idempotency key. Same key with same request returns cached response. Keys expire after 24 hours.
e.g. "550e8400-e29b-41d4-a716-446655440000"

Request body required

FieldTypeDescription
name
string
e.g. "Premium Coaching Program v2"
description
string
e.g. "Updated 14-week intensive coaching program"
pricing
object
amount
integer
e.g. 34900
currency
string
e.g. "usd"
requires_shipping
boolean
e.g. false
sku
string
e.g. "coaching_premium_14wk"
availability
enum
in_stockout_of_stockpreorder
e.g. "in_stock"
category
string
e.g. "Coaching"
brand
string
e.g. "Elite Academy"
material
string
e.g. "Cotton blend"
weight
string
e.g. "0.5 kg"
return_window
integer
e.g. 30
inventory_quantity
integer
e.g. 200
active
boolean
Set to `false` to archive the product. Archived products cannot be used in new orders.
e.g. true
metadata
Metadata

Responses

200 The updated product.
FieldTypeDescription
idrequired
string
e.g. "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
namerequired
string
e.g. "Premium Coaching Program"
descriptionnullable
string
e.g. "12-week intensive coaching program"
pricingrequired
object
amountrequired
integer
Price in cents.
e.g. 29700
currencyrequired
string
Three-letter ISO 4217 currency code.
e.g. "usd"
requires_shippingrequired
boolean
e.g. false
skurequired
string
Unique stock keeping unit.
e.g. "coaching_premium_12wk"
availabilityrequired
enum
in_stockout_of_stockpreorder
e.g. "in_stock"
categorynullable
string
e.g. "Coaching"
brandnullable
string
e.g. "Elite Academy"
materialnullable
string
e.g. "Cotton blend"
weightnullable
string
e.g. "0.5 kg"
return_windownullable
integer
Return window in days (0-365).
e.g. 30
inventory_quantitynullable
integer
Available inventory count.
e.g. 150
images
array[ProductImage]
metadata
Metadata
activerequired
boolean
e.g. true
created_atrequired
string (date-time)
e.g. "2024-01-15T10:30:00.000Z"
updated_atrequired
string (date-time)
e.g. "2024-01-15T10:30:00.000Z"
400 Bad Request — The request was invalid or cannot be served.
FieldTypeDescription
errorrequired
object
typerequired
enum
The type of error.
invalid_request_errorauthentication_errorauthorization_errorrate_limit_erroridempotency_errorprocessing_errorwebhook_error
coderequired
string
A short string identifying the specific error.
e.g. "validation_error"
messagerequired
string
A human-readable message providing details about the error.
e.g. "Request validation failed"
paramnullable
string
The parameter that caused the error, if applicable.
e.g. "email"
request_id
string
Unique request identifier for debugging.
e.g. "req_a1b2c3d4e5f67890abcdef0123456789"
field_errors
array[object]
Detailed field-level errors for validation failures.
404 Not Found — The requested resource doesn't exist.
FieldTypeDescription
errorrequired
object
typerequired
enum
The type of error.
invalid_request_errorauthentication_errorauthorization_errorrate_limit_erroridempotency_errorprocessing_errorwebhook_error
coderequired
string
A short string identifying the specific error.
e.g. "validation_error"
messagerequired
string
A human-readable message providing details about the error.
e.g. "Request validation failed"
paramnullable
string
The parameter that caused the error, if applicable.
e.g. "email"
request_id
string
Unique request identifier for debugging.
e.g. "req_a1b2c3d4e5f67890abcdef0123456789"
field_errors
array[object]
Detailed field-level errors for validation failures.
409 Conflict — The request conflicts with existing data.
FieldTypeDescription
errorrequired
object
typerequired
enum
The type of error.
invalid_request_errorauthentication_errorauthorization_errorrate_limit_erroridempotency_errorprocessing_errorwebhook_error
coderequired
string
A short string identifying the specific error.
e.g. "validation_error"
messagerequired
string
A human-readable message providing details about the error.
e.g. "Request validation failed"
paramnullable
string
The parameter that caused the error, if applicable.
e.g. "email"
request_id
string
Unique request identifier for debugging.
e.g. "req_a1b2c3d4e5f67890abcdef0123456789"
field_errors
array[object]
Detailed field-level errors for validation failures.
DELETE /products/{id}

Delete a product

Deletes a product. Cannot delete products used in active plans.

Condition Behavior
In active plans Blocked (400 error)
Has order history or archived plans Soft delete
No orders or plans Hard delete

Path parameters

NameTypeDescription
idrequired
string
e.g. "6ba7b810-9dad-11d1-80b4-00c04fd430c8"

Header parameters

NameTypeDescription
EPD-Version
string
API version override (format `YYYY-MM-DD`). If omitted, your account's pinned version or the latest version is used.
e.g. "2026-02-11"
X-EPD-Idempotency-Key
string (uuid)
Optional UUID v4 idempotency key for retry safety.
e.g. "550e8400-e29b-41d4-a716-446655440000"

Responses

200 Product deleted.
FieldTypeDescription
idrequired
string
e.g. "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
deletedrequired
true
messagerequired
string
e.g. "Product successfully deleted."
400 Bad Request — The request was invalid or cannot be served.
FieldTypeDescription
errorrequired
object
typerequired
enum
The type of error.
invalid_request_errorauthentication_errorauthorization_errorrate_limit_erroridempotency_errorprocessing_errorwebhook_error
coderequired
string
A short string identifying the specific error.
e.g. "validation_error"
messagerequired
string
A human-readable message providing details about the error.
e.g. "Request validation failed"
paramnullable
string
The parameter that caused the error, if applicable.
e.g. "email"
request_id
string
Unique request identifier for debugging.
e.g. "req_a1b2c3d4e5f67890abcdef0123456789"
field_errors
array[object]
Detailed field-level errors for validation failures.
404 Not Found — The requested resource doesn't exist.
FieldTypeDescription
errorrequired
object
typerequired
enum
The type of error.
invalid_request_errorauthentication_errorauthorization_errorrate_limit_erroridempotency_errorprocessing_errorwebhook_error
coderequired
string
A short string identifying the specific error.
e.g. "validation_error"
messagerequired
string
A human-readable message providing details about the error.
e.g. "Request validation failed"
paramnullable
string
The parameter that caused the error, if applicable.
e.g. "email"
request_id
string
Unique request identifier for debugging.
e.g. "req_a1b2c3d4e5f67890abcdef0123456789"
field_errors
array[object]
Detailed field-level errors for validation failures.