Subscriptions represent recurring billing arrangements between a customer and a plan.

Billing Cadence Options

Cadence Configuration
Weekly interval: "day", interval_count: 7
Bi-weekly interval: "day", interval_count: 14
Monthly interval: "month", interval_count: 1
Quarterly interval: "month", interval_count: 3
Annually interval: "month", interval_count: 12

Termination Strategies

Strategy How
Bill forever Omit billing_cycles and end_date
After N cycles Set billing_cycles: 12
Until a date Set end_date: "2025-12-31"

Status Lifecycle

active → paused → active (resume)
active → canceled
active → completed (all cycles finished)
active → past_due (payment failed)
POST /subscriptions

Create a subscription

Creates a new recurring billing subscription for a customer using a plan and payment method.

Prerequisites

Before creating a subscription, you need:

  1. A customer with at least one payment method
  2. A plan (created via the merchant dashboard)
  3. A payment method attached to the customer

Billing Cadence Options

Day-based: Charge every N days — ideal for custom intervals.

{ "interval": "day", "interval_count": 30 }

Month-based: Charge on a specific day of the month. If the month has fewer days than anchor_day, billing occurs on the last day of the month.

{ "interval": "month", "interval_count": 1, "anchor_day": 15 }

Subscription Duration

Strategy Configuration Example
Bills forever Omit billing_cycles and end_date Ongoing membership
After N cycles billing_cycles: 12 12-month program
Until a date end_date: "2025-12-31" School year subscription

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
customer_idrequired
string
e.g. "550e8400-e29b-41d4-a716-446655440000"
plan_idrequired
string
e.g. "6ba7b814-9dad-11d1-80b4-00c04fd430d0"
payment_method_idrequired
string
e.g. "6ba7b815-9dad-11d1-80b4-00c04fd430d1"
billing_cyclerequired
object
intervalrequired
enum
daymonth
e.g. "month"
interval_countrequired
integer
e.g. 1
anchor_day
integer
Day of month for billing (month-based only).
e.g. 15
end_date
string (date)
End date in ISO 8601 format. Must be after start_date.
e.g. "2025-02-01"
billing_cycles
integer
Number of billing cycles (`0` = unlimited).
e.g. 12
shipping_address_id
string
ID of an existing shipping address.
e.g. "42"
shipping_address
object
Create a new shipping address.
first_namerequired
string
e.g. "John"
last_namerequired
string
e.g. "Doe"
address_line1required
string
e.g. "123 Main St"
address_line2
string
e.g. "Suite 100"
cityrequired
string
e.g. "San Francisco"
staterequired
string
e.g. "CA"
postal_coderequired
string
e.g. "94105"
countryrequired
string
e.g. "US"
phone
string
Phone number in E.164 format.
e.g. "+14155551234"
shipping_option_id
string
Shipping option ID. Requires a shipping address.
e.g. "6ba7b818-9dad-11d1-80b4-00c04fd430c8"
coupon_code
string
Optional coupon code to apply to the subscription's first billing cycle. Case-insensitive. Subsequent cycles reuse the redemption snapshot per the coupon's `duration`. Invalid or ineligible codes return a `400` with a structured `error.code` (e.g. `coupon_expired`, `plan_not_eligible`); the subscription is not created.
e.g. "SAVE10"

Code samples

curl -X POST https://api.epd.com/v1/subscriptions \
  -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 '{
    "customer_id": "550e8400-e29b-41d4-a716-446655440000",
    "plan_id": "6ba7b814-9dad-11d1-80b4-00c04fd430d0",
    "payment_method_id": "6ba7b815-9dad-11d1-80b4-00c04fd430d1",
    "billing_cycle": {
      "interval": "month",
      "interval_count": 1,
      "anchor_day": 15
    }
  }'
const response = await fetch('https://api.epd.com/v1/subscriptions', {
  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({
    customer_id: '550e8400-e29b-41d4-a716-446655440000',
    plan_id: '6ba7b814-9dad-11d1-80b4-00c04fd430d0',
    payment_method_id: '6ba7b815-9dad-11d1-80b4-00c04fd430d1',
    billing_cycle: {
      interval: 'month',
      interval_count: 1,
      anchor_day: 15,
    },
  }),
});

const subscription = await response.json();
console.log(subscription.id);     // 6ba7b812-9dad-11d1-80b4-00c04fd430c8
console.log(subscription.status); // "active"
import uuid
import requests

response = requests.post(
    'https://api.epd.com/v1/subscriptions',
    headers={
        'Authorization': 'Bearer epd_test_sk_xxxx',
        'EPD-Version': '2026-02-11',
        'X-EPD-Idempotency-Key': str(uuid.uuid4()),
    },
    json={
        'customer_id': '550e8400-e29b-41d4-a716-446655440000',
        'plan_id': '6ba7b814-9dad-11d1-80b4-00c04fd430d0',
        'payment_method_id': '6ba7b815-9dad-11d1-80b4-00c04fd430d1',
        'billing_cycle': {
            'interval': 'month',
            'interval_count': 1,
            'anchor_day': 15,
        },
    }
)

sub = response.json()
print(sub['id'])     # 6ba7b812-9dad-11d1-80b4-00c04fd430c8
print(sub['status']) # "active"
$ch = curl_init('https://api.epd.com/v1/subscriptions');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer epd_test_sk_xxxx',
        'Content-Type: application/json',
        'EPD-Version: 2026-02-11',
        'X-EPD-Idempotency-Key: ' . wp_generate_uuid4(),
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'customer_id' => '550e8400-e29b-41d4-a716-446655440000',
        'plan_id' => '6ba7b814-9dad-11d1-80b4-00c04fd430d0',
        'payment_method_id' => '6ba7b815-9dad-11d1-80b4-00c04fd430d1',
        'billing_cycle' => [
            'interval' => 'month',
            'interval_count' => 1,
            'anchor_day' => 15,
        ],
    ]),
]);

$sub = json_decode(curl_exec($ch), true);
echo $sub['status']; // "active"

Responses

201 Subscription created.
FieldTypeDescription
idrequired
string
e.g. "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
customer_idrequired
string
e.g. "550e8400-e29b-41d4-a716-446655440002"
plannullable
object
id
string
e.g. "6ba7b814-9dad-11d1-80b4-00c04fd430d2"
name
string
e.g. "Premium Monthly"
amount
integer
e.g. 2999
currency
string
e.g. "usd"
statusrequired
enum
activepausedcanceledcompletedpast_duefailed
e.g. "active"
billing_cyclerequired
BillingCycle
payment_methodnullable
object
id
string
e.g. "6ba7b815-9dad-11d1-80b4-00c04fd430d2"
card_last_four
string
e.g. "4242"
card_brand
string
e.g. "visa"
shipping_addressnullable
object
id
string (uuid)
first_name
string
last_name
string
address_line1
string
address_line2nullable
string
city
string
state
string
postal_code
string
country
string
phonenullable
string
current_period_startnullable
string (date-time)
ISO 8601 timestamp for start of current billing period.
e.g. "2024-01-15T10:30:00.000Z"
current_period_endnullable
string (date-time)
ISO 8601 timestamp for end of current billing period.
e.g. "2024-02-15T10:30:00.000Z"
current_billing_cyclerequired
integer
Current billing cycle number.
e.g. 3
total_billing_cyclesrequired
integer
Total billing cycles (`0` = unlimited).
e.g. 12
next_billing_datenullable
string (date-time)
ISO 8601 timestamp of next billing date.
e.g. "2024-02-15T10:30:00.000Z"
start_daterequired
string (date-time)
ISO 8601 timestamp when the subscription was created (immutable).
e.g. "2023-11-15T00:00:00.000Z"
end_datenullable
string (date-time)
ISO 8601 timestamp when subscription terminates.
e.g. "2024-11-15T00:00:00.000Z"
canceled_atnullable
string (date-time)
ISO 8601 timestamp when subscription was canceled.
applied_couponrequired
object
Coupon details captured at redemption time, frozen on the redemption snapshot. `null` when no coupon was applied. Snapshot fields (`amount`, `percentage`, `max_discount_amount`, `currency`, `duration`, `duration_in_cycles`) reflect the coupon as it existed at first redemption and do **not** change if the underlying coupon is later edited. Renewal cycles read these snapshot values until the `duration` window completes.
idrequired
string (uuid)
e.g. "6ba7b820-9dad-11d1-80b4-00c04fd430c8"
coderequired
string
e.g. "SAVE10"
namerequired
string
e.g. "Holiday Promo"
kindrequired
enum
generatedpromo
e.g. "promo"
percentagenullable
number
Percent discount (0–100) for percentage coupons; `null` for amount-off coupons.
e.g. 10
amountnullable
integer
Amount-off in cents for amount-off coupons; `null` for percentage coupons.
e.g. null
max_discount_amountnullable
integer
Maximum discount cap in cents, frozen at redemption time. Only applies to percentage-off coupons (always `null` for amount-off). Mirrors the snapshot stored on the redemption row, so historical subscriptions keep their original cap even if the live coupon's cap is later edited.
e.g. 500
currencyrequired
string
e.g. "usd"
durationrequired
enum
oncerepeatingforever
e.g. "repeating"
duration_in_cyclesnullable
integer
Number of billing cycles the discount applies to when `duration` is `repeating`; `null` otherwise.
e.g. 3
discount_amountrequired
integer
Discount applied to the **first** billing cycle in cents. Subsequent cycles compute their own discount from the snapshot until `duration` completes.
e.g. 300
created_atrequired
string (date-time)
e.g. "2023-11-15T00:00: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.
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.
429 Too Many Requests — Rate limit exceeded.
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 /subscriptions

List all subscriptions

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"
customer_id
string
Filter by customer ID.
e.g. "550e8400-e29b-41d4-a716-446655440000"
status
string
Filter by status: `active`, `paused`, `canceled`, `completed`, `past_due`.
e.g. "active"
plan_id
string
Filter by plan ID.
e.g. "6ba7b814-9dad-11d1-80b4-00c04fd430d0"
expand
string
Expand: `customer`, `plan`, `cycles`.
e.g. "customer,plan"
sort
string
Sort order. Format: `field[direction]` or `-field` for descending. Default: `created_at[desc]`.
e.g. "created_at[desc]"
fields[subscriptions]
string
Sparse fieldsets — comma-separated list of fields to include (e.g., `id,status,customer_id,created`).
e.g. "id,status,customer_id,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 subscriptions.
FieldTypeDescription
data
array[Subscription]
url
any
e.g. "/v1/subscriptions"
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 /subscriptions/{id}

Retrieve a subscription

Path parameters

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

Query parameters

NameTypeDescription
expand
string
Comma-separated: `customer`, `plan`, `cycles`.

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 subscription.
FieldTypeDescription
idrequired
string
e.g. "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
customer_idrequired
string
e.g. "550e8400-e29b-41d4-a716-446655440002"
plannullable
object
id
string
e.g. "6ba7b814-9dad-11d1-80b4-00c04fd430d2"
name
string
e.g. "Premium Monthly"
amount
integer
e.g. 2999
currency
string
e.g. "usd"
statusrequired
enum
activepausedcanceledcompletedpast_duefailed
e.g. "active"
billing_cyclerequired
BillingCycle
payment_methodnullable
object
id
string
e.g. "6ba7b815-9dad-11d1-80b4-00c04fd430d2"
card_last_four
string
e.g. "4242"
card_brand
string
e.g. "visa"
shipping_addressnullable
object
id
string (uuid)
first_name
string
last_name
string
address_line1
string
address_line2nullable
string
city
string
state
string
postal_code
string
country
string
phonenullable
string
current_period_startnullable
string (date-time)
ISO 8601 timestamp for start of current billing period.
e.g. "2024-01-15T10:30:00.000Z"
current_period_endnullable
string (date-time)
ISO 8601 timestamp for end of current billing period.
e.g. "2024-02-15T10:30:00.000Z"
current_billing_cyclerequired
integer
Current billing cycle number.
e.g. 3
total_billing_cyclesrequired
integer
Total billing cycles (`0` = unlimited).
e.g. 12
next_billing_datenullable
string (date-time)
ISO 8601 timestamp of next billing date.
e.g. "2024-02-15T10:30:00.000Z"
start_daterequired
string (date-time)
ISO 8601 timestamp when the subscription was created (immutable).
e.g. "2023-11-15T00:00:00.000Z"
end_datenullable
string (date-time)
ISO 8601 timestamp when subscription terminates.
e.g. "2024-11-15T00:00:00.000Z"
canceled_atnullable
string (date-time)
ISO 8601 timestamp when subscription was canceled.
applied_couponrequired
object
Coupon details captured at redemption time, frozen on the redemption snapshot. `null` when no coupon was applied. Snapshot fields (`amount`, `percentage`, `max_discount_amount`, `currency`, `duration`, `duration_in_cycles`) reflect the coupon as it existed at first redemption and do **not** change if the underlying coupon is later edited. Renewal cycles read these snapshot values until the `duration` window completes.
idrequired
string (uuid)
e.g. "6ba7b820-9dad-11d1-80b4-00c04fd430c8"
coderequired
string
e.g. "SAVE10"
namerequired
string
e.g. "Holiday Promo"
kindrequired
enum
generatedpromo
e.g. "promo"
percentagenullable
number
Percent discount (0–100) for percentage coupons; `null` for amount-off coupons.
e.g. 10
amountnullable
integer
Amount-off in cents for amount-off coupons; `null` for percentage coupons.
e.g. null
max_discount_amountnullable
integer
Maximum discount cap in cents, frozen at redemption time. Only applies to percentage-off coupons (always `null` for amount-off). Mirrors the snapshot stored on the redemption row, so historical subscriptions keep their original cap even if the live coupon's cap is later edited.
e.g. 500
currencyrequired
string
e.g. "usd"
durationrequired
enum
oncerepeatingforever
e.g. "repeating"
duration_in_cyclesnullable
integer
Number of billing cycles the discount applies to when `duration` is `repeating`; `null` otherwise.
e.g. 3
discount_amountrequired
integer
Discount applied to the **first** billing cycle in cents. Subsequent cycles compute their own discount from the snapshot until `duration` completes.
e.g. 300
created_atrequired
string (date-time)
e.g. "2023-11-15T00:00: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 /subscriptions/{id}

Update a subscription

Updates a subscription. Only subscriptions with status active or paused can be modified.

Path parameters

NameTypeDescription
idrequired
string
e.g. "6ba7b812-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
payment_method_id
string
New payment method ID.
e.g. "6ba7b815-9dad-11d1-80b4-00c04fd430c8"
shipping_address_id
string
Use an existing shipping address.
e.g. "42"
shipping_address
object
Create a new shipping address.
first_name
string
e.g. "John"
last_name
string
e.g. "Doe"
address_line1
string
e.g. "456 Oak Ave"
address_line2
string
e.g. "Apt 2B"
city
string
e.g. "Austin"
state
string
e.g. "TX"
postal_code
string
e.g. "73301"
country
string
e.g. "US"
phone
string
Phone number in E.164 format.
e.g. "+15125559876"
shipping_option_id
string
e.g. "6ba7b819-9dad-11d1-80b4-00c04fd430c8"
billing_cycle
object
interval
enum
daymonth
e.g. "month"
interval_count
integer
e.g. 1
anchor_day
integer
e.g. 15

Responses

200 The updated subscription.
FieldTypeDescription
idrequired
string
e.g. "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
customer_idrequired
string
e.g. "550e8400-e29b-41d4-a716-446655440002"
plannullable
object
id
string
e.g. "6ba7b814-9dad-11d1-80b4-00c04fd430d2"
name
string
e.g. "Premium Monthly"
amount
integer
e.g. 2999
currency
string
e.g. "usd"
statusrequired
enum
activepausedcanceledcompletedpast_duefailed
e.g. "active"
billing_cyclerequired
BillingCycle
payment_methodnullable
object
id
string
e.g. "6ba7b815-9dad-11d1-80b4-00c04fd430d2"
card_last_four
string
e.g. "4242"
card_brand
string
e.g. "visa"
shipping_addressnullable
object
id
string (uuid)
first_name
string
last_name
string
address_line1
string
address_line2nullable
string
city
string
state
string
postal_code
string
country
string
phonenullable
string
current_period_startnullable
string (date-time)
ISO 8601 timestamp for start of current billing period.
e.g. "2024-01-15T10:30:00.000Z"
current_period_endnullable
string (date-time)
ISO 8601 timestamp for end of current billing period.
e.g. "2024-02-15T10:30:00.000Z"
current_billing_cyclerequired
integer
Current billing cycle number.
e.g. 3
total_billing_cyclesrequired
integer
Total billing cycles (`0` = unlimited).
e.g. 12
next_billing_datenullable
string (date-time)
ISO 8601 timestamp of next billing date.
e.g. "2024-02-15T10:30:00.000Z"
start_daterequired
string (date-time)
ISO 8601 timestamp when the subscription was created (immutable).
e.g. "2023-11-15T00:00:00.000Z"
end_datenullable
string (date-time)
ISO 8601 timestamp when subscription terminates.
e.g. "2024-11-15T00:00:00.000Z"
canceled_atnullable
string (date-time)
ISO 8601 timestamp when subscription was canceled.
applied_couponrequired
object
Coupon details captured at redemption time, frozen on the redemption snapshot. `null` when no coupon was applied. Snapshot fields (`amount`, `percentage`, `max_discount_amount`, `currency`, `duration`, `duration_in_cycles`) reflect the coupon as it existed at first redemption and do **not** change if the underlying coupon is later edited. Renewal cycles read these snapshot values until the `duration` window completes.
idrequired
string (uuid)
e.g. "6ba7b820-9dad-11d1-80b4-00c04fd430c8"
coderequired
string
e.g. "SAVE10"
namerequired
string
e.g. "Holiday Promo"
kindrequired
enum
generatedpromo
e.g. "promo"
percentagenullable
number
Percent discount (0–100) for percentage coupons; `null` for amount-off coupons.
e.g. 10
amountnullable
integer
Amount-off in cents for amount-off coupons; `null` for percentage coupons.
e.g. null
max_discount_amountnullable
integer
Maximum discount cap in cents, frozen at redemption time. Only applies to percentage-off coupons (always `null` for amount-off). Mirrors the snapshot stored on the redemption row, so historical subscriptions keep their original cap even if the live coupon's cap is later edited.
e.g. 500
currencyrequired
string
e.g. "usd"
durationrequired
enum
oncerepeatingforever
e.g. "repeating"
duration_in_cyclesnullable
integer
Number of billing cycles the discount applies to when `duration` is `repeating`; `null` otherwise.
e.g. 3
discount_amountrequired
integer
Discount applied to the **first** billing cycle in cents. Subsequent cycles compute their own discount from the snapshot until `duration` completes.
e.g. 300
created_atrequired
string (date-time)
e.g. "2023-11-15T00:00: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.
DELETE /subscriptions/{id}

Cancel a subscription

Cancels a subscription immediately. The subscription status changes to canceled and no further billing cycles are processed.

Eligibility

Current Status Can Cancel? Notes
active Yes Stops future billing
paused Yes Cancels permanently
canceled No Returns 400 (already canceled)
completed No Returns 400 (already finished)

Important: Cancellation is immediate and permanent. There is no "cancel at end of period" option — the subscription ends now. To bill through the current period, wait until current_period_end before canceling.

Path parameters

NameTypeDescription
idrequired
string
Subscription ID (UUID).
e.g. "6ba7b812-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"

Code samples

curl -X DELETE https://api.epd.com/v1/subscriptions/6ba7b812-9dad-11d1-80b4-00c04fd430c8 \
  -H "Authorization: Bearer epd_test_sk_xxxx" \
  -H "EPD-Version: 2026-02-11" \
  -H "X-EPD-Idempotency-Key: $(uuidgen)"
const response = await fetch('https://api.epd.com/v1/subscriptions/6ba7b812-9dad-11d1-80b4-00c04fd430c8', {
  method: 'DELETE',
  headers: {
    'Authorization': 'Bearer epd_test_sk_xxxx',
    'EPD-Version': '2026-02-11',
    'X-EPD-Idempotency-Key': crypto.randomUUID(),
  },
});

const result = await response.json();
console.log(result.status); // "canceled"
import uuid
import requests

response = requests.delete(
    'https://api.epd.com/v1/subscriptions/6ba7b812-9dad-11d1-80b4-00c04fd430c8',
    headers={
        'Authorization': 'Bearer epd_test_sk_xxxx',
        'EPD-Version': '2026-02-11',
        'X-EPD-Idempotency-Key': str(uuid.uuid4()),
    }
)

result = response.json()
print(result['status'])  # "canceled"

Responses

200 Subscription canceled.
FieldTypeDescription
idrequired
string
e.g. "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
statusrequired
"canceled"
actionrequired
"canceled"
effective_daterequired
string (date-time)
ISO 8601 timestamp when cancellation takes effect.
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.