Requires the Reload plugin. Subscriptions are a Reload feature. If your store does not have Reload installed and active, there is nothing for these endpoints to act on — and, importantly, deactivating Reload stops all recurring charges, including for subscriptions that already exist. See What happens without Reload for the exact behaviour.
A subscription is a recurring order created by the Reload plugin: a set of line items, a cadence, a stored card and a shipping address that together produce a new order every cycle. These endpoints let you act on those subscriptions from your own systems the same way a merchant would from the dashboard — every change routes through the same service the customer self-serve portal uses and lands in the subscription’s audit trail with the actor recorded as merchant.
Use them to build a subscriber view in your CRM, to honour a “pause my box” request from your own support desk, or to reconcile upcoming charges against inventory. Read access needs the subscriptions:read ability; every mutation needs subscriptions:write. See Authentication for how abilities are attached to a token. All seven endpoints share the standard 60 requests-per-minute-per-team budget.
What this API cannot do
There is no create and no delete. Subscriptions come into existence only when a shopper checks out through a Reload-enabled storefront, and they are ended by cancelling, never removed. Cancellation is also one-way here: /resume explicitly refuses a cancelled subscription, and the reactivation path exists only in the dashboard.
What happens without Reload
The routes themselves are not gated — they return 200, not a 403, whether or not the plugin is active. What changes is what exists and what runs:
| Reload state | Reading | Recurring charges |
|---|---|---|
| Installed and active | Normal | Run hourly as scheduled |
| Never installed | Valid, empty data array |
Nothing to charge |
| Installed then deactivated | Existing subscriptions still list and still accept mutations | Stop immediately |
That third row is the one that catches people. Deactivating Reload halts billing for every subscription on the store — the hourly charge run filters to teams with the plugin active, so a subscription can sit in this API reporting status: "active" with a next_charge_at in the past while nothing is actually being billed. Charges resume on the next hourly tick if the merchant reactivates.
Because the routes never error, an empty data array is not evidence of a misconfiguration, and a populated one is not evidence that billing is running. If you are reconciling revenue, confirm the plugin state in the dashboard rather than inferring it from this API.
Subscriptions are keyed by UUID
Every other v1 resource is addressed by its per-store number. Subscriptions are the exception: the path parameter is the uuid field, and subscription_id is a display number for merchant-facing screens only. Passing a subscription_id — or anything else that is not a well-formed UUID — does not return a 404: the path segment reaches a UUID-typed column unguarded and the request fails as a 500. A 404 means a well-formed UUID that no subscription on your store carries.
The customer_id on a subscription is the same value the Customers API returns, so the two line up. The shipping_address_id and payment_method_id accepted by PATCH are UUIDs: take address_id from any address object in a v1 response, and payment_method_id from the subscription’s own payment_method block.
Every mutation returns 200, even when nothing happened
This is the single most important thing to know about the four action endpoints. Pause, resume, skip and cancel each check an eligibility rule before doing any work, and when that rule fails they return early and still respond 200 with the unchanged subscription. There is no error, no flag, and no distinguishing field.
| Action | Only takes effect when status is |
|---|---|
pause |
active |
resume |
paused or past_due |
skip |
active |
cancel |
active, paused or past_due |
PATCH behaves the same way for cadence: sending the cadence the subscription already has writes nothing and logs no event.
Always read the returned resource rather than trusting the status code. Check data.status after pause, resume and cancel, and compare data.next_charge_at against the value you started from after a skip.
Reading the response
A few shapes are easy to get wrong:
- Money mixes units.
items[].unit_priceis in dollars (24.99), not cents.discount_pctis a whole percentage between 0 and 50 applied to the recurring subtotal —10means 10% off, not $10 and not 0.1. Whole values lose their decimal point in JSON, so both fields arrive as integers on some rows and floats on others; parse them as numbers. shipping_addressis nevernull. When there is no address, or the customer soft-deleted the one the subscription pointed at, the key is still an object:address_idand every street field readnull, the two role booleans readfalse, andtypestill reads"shipping". Testshipping_address.address_line1, not the key.payment_methodandcustomer_id, by contrast, do come back asnullin the equivalent situation.- Some stored state is not exposed.
paused_until,cancelled_at,cancellation_reason, the last decline type, the billing address and the merchant account have no representation in the response, so a reason you write viacancelcannot be read back. - Pagination links drop your filters.
links.nextand the entries inmeta.linkscarry only?page=N. Re-applystatus,customer_idandper_pageon each request instead of following those URLs as-is.
Timestamps
All timestamps are ISO 8601 with an explicit UTC offset (2026-09-01T14:00:00+00:00). Cadence arithmetic is calendar-based — one, three, six or twelve months — not a fixed number of days, and it preserves the time of day, so a subscription that bills at 14:00 on the 1st keeps billing at 14:00 on the 1st.
List subscriptions
/v1/subscriptions- Required ability
subscriptions:read- Rate limit
- 60 requests/minute per team
Query parameters
statusstringoptional- Exact-match filter on subscription status. One of `active`, `paused`, `past_due`, `cancelled`.Example:
active customer_idintegeroptional- Restrict to one customer, matched on the `customer_id` the Customers API returns — the store-scoped number, not a database key.Example:
1187 per_pageintegeroptional- Results per page. Defaults to 25, capped at 100.Example:
50 pageintegeroptional- 1-based page number. Defaults to 1.Example:
2
- Pagination links drop your filters. `paginate()` is called without `withQueryString()`, so `links.next` and `meta.links[].url` contain only `?page=N` — following them verbatim silently widens the result set. Re-apply `status`, `customer_id` and `per_page` yourself on every page request.
- `status` is not validated. An unrecognised value is passed straight into the `where` clause and returns an empty `data` array with `total: 0`, not a 422.
- `customer_id` is not validated either, and it maps to a bigint column — a non-numeric value (`?customer_id=abc`) reaches the database as an invalid integer literal and surfaces as a 500.
- `per_page` is capped but not floored: `per_page=0` falls back to an internal default of 15, and a negative value drops the SQL `LIMIT` entirely and returns every subscription the team has in a single page.
- Money units differ by field. `items[].unit_price` is **dollars** (the stored cents divided by 100) while `discount_pct` is a whole percentage in the range 0–50 — `10` means 10% off the recurring subtotal, not $10 and not 0.1.
- PHP serializes whole-dollar and whole-percent values without a decimal point, so `unit_price` and `discount_pct` arrive as JSON integers (`189`, `10`) on some rows and JSON floats (`24.99`) on others. Parse them as numbers, not as fixed-shape decimals.
curl "https://api.firearmcart.com/v1/subscriptions?status=active&per_page=25" \
-H "Authorization: Bearer $FIREARMCART_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"uuid": "9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31",
"subscription_id": 1042,
"status": "active",
"cadence": "monthly",
"cadence_label": "Monthly",
"discount_pct": 10,
"next_charge_at": "2026-09-01T14:00:00+00:00",
"last_charged_at": "2026-08-01T14:00:00+00:00",
"failed_charge_count": 0,
"customer_id": 1187,
"items": [
{
"product_id": 2043,
"variant_id": 5581,
"quantity": 2,
"unit_price": 24.99
}
],
"shipping_address": {
"address_id": "6e1d9f27-3c4b-4a85-b1e0-5d8c2f7a94b3",
"type": "shipping",
"address_line1": "418 Ridgeline Dr",
"address_line2": null,
"city": "Bozeman",
"state": "MT",
"zip_code": "59718",
"is_billing": false,
"is_shipping": true,
"is_default_billing": false,
"is_default_shipping": true
},
"payment_method": {
"payment_method_id": "2b9e4c61-8a05-4f7d-9c33-1e6b0d5a82f4",
"brand": "visa",
"last_four": "4242"
},
"created_at": "2026-03-14T09:22:07+00:00",
"updated_at": "2026-08-01T14:00:03+00:00"
},
{
"uuid": "3d6b90a7-52c1-4f0e-8a44-b17e9c25d380",
"subscription_id": 1039,
"status": "paused",
"cadence": "quarterly",
"cadence_label": "Every 3 months",
"discount_pct": 0,
"next_charge_at": "2026-10-02T16:30:00+00:00",
"last_charged_at": "2026-07-02T16:30:00+00:00",
"failed_charge_count": 0,
"customer_id": 1204,
"items": [
{
"product_id": 1877,
"variant_id": null,
"quantity": 1,
"unit_price": 189
}
],
"shipping_address": {
"address_id": null,
"type": "shipping",
"address_line1": null,
"address_line2": null,
"city": null,
"state": null,
"zip_code": null,
"is_billing": false,
"is_shipping": false,
"is_default_billing": null,
"is_default_shipping": null
},
"payment_method": null,
"created_at": "2026-01-08T18:41:55+00:00",
"updated_at": "2026-07-19T11:02:14+00:00"
}
],
"links": {
"first": "https://api.firearmcart.com/v1/subscriptions?page=1",
"last": "https://api.firearmcart.com/v1/subscriptions?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"links": [
{
"url": null,
"label": "« Previous",
"page": null,
"active": false
},
{
"url": "https://api.firearmcart.com/v1/subscriptions?page=1",
"label": "1",
"page": 1,
"active": true
},
{
"url": null,
"label": "Next »",
"page": null,
"active": false
}
],
"path": "https://api.firearmcart.com/v1/subscriptions",
"per_page": 25,
"to": 2,
"total": 2
}
}{
"message": "Invalid ability provided."
}Retrieve a subscription
/v1/subscriptions/{uuid}- Required ability
subscriptions:read- Rate limit
- 60 requests/minute per team
Path parameters
uuidstringrequired- The subscription's `uuid`. Subscriptions are the one v1 resource keyed by UUID rather than a per-store number — the `subscription_id` in the response is a display number and is not accepted here.Example:
9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31
- A malformed `uuid` is a 500, not a 404. None of the seven subscription routes check the path segment's format before querying, so a value that is not a well-formed UUID — a `subscription_id`, a truncated string — reaches the UUID-typed column and the database rejects it. Only a well-formed UUID that does not exist on your store returns the 404 above.
- Several stored fields are deliberately not exposed: `paused_until`, `cancelled_at`, `cancellation_reason`, `last_decline_type`, `billing_address_id` and `merchant_account_id` have no representation in the response.
- `shipping_address` is never `null`. When the subscription has no shipping address — or the customer soft-deleted the one it pointed at — the key is still an object, with every field `null`, `is_billing`/`is_shipping` `false` and `type` `"shipping"`. Test `shipping_address.address_line1` rather than the key itself.
- `payment_method` and `customer_id` *do* go `null` when their records are missing or soft-deleted, so the two nested objects behave inconsistently with each other.
- `payment_method` carries the card's `payment_method_id` UUID plus `brand` and `last_four` — the id is what `PATCH` accepts back.
curl https://api.firearmcart.com/v1/subscriptions/9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31 \
-H "Authorization: Bearer $FIREARMCART_TOKEN" \
-H "Accept: application/json"{
"data": {
"uuid": "9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31",
"subscription_id": 1042,
"status": "active",
"cadence": "monthly",
"cadence_label": "Monthly",
"discount_pct": 10,
"next_charge_at": "2026-09-01T14:00:00+00:00",
"last_charged_at": "2026-08-01T14:00:00+00:00",
"failed_charge_count": 0,
"customer_id": 1187,
"items": [
{
"product_id": 2043,
"variant_id": 5581,
"quantity": 2,
"unit_price": 24.99
}
],
"shipping_address": {
"address_id": "6e1d9f27-3c4b-4a85-b1e0-5d8c2f7a94b3",
"type": "shipping",
"address_line1": "418 Ridgeline Dr",
"address_line2": null,
"city": "Bozeman",
"state": "MT",
"zip_code": "59718",
"is_billing": false,
"is_shipping": true,
"is_default_billing": false,
"is_default_shipping": true
},
"payment_method": {
"payment_method_id": "2b9e4c61-8a05-4f7d-9c33-1e6b0d5a82f4",
"brand": "visa",
"last_four": "4242"
},
"created_at": "2026-03-14T09:22:07+00:00",
"updated_at": "2026-08-01T14:00:03+00:00"
}
}{
"error": "not_found",
"message": "Subscription not found."
}Update a subscription
/v1/subscriptions/{uuid}- Required ability
subscriptions:write- Rate limit
- 60 requests/minute per team
Path parameters
uuidstringrequired- The subscription's `uuid`.Example:
9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31
Body parameters
cadencestringoptional- New billing interval. One of `monthly`, `quarterly`, `semiannual`, `yearly`. Anything else is a validation error.Example:
quarterly shipping_address_idstring (uuid)optional- The `address_id` UUID of an address belonging to this subscription's customer — the value every address object in v1 responses carries (customer show, order show, this resource's `shipping_address`).Example:
6e1d9f27-3c4b-4a85-b1e0-5d8c2f7a94b3 payment_method_idstring (uuid)optional- The `payment_method_id` UUID of a stored card belonging to this subscription's customer — returned inside this resource's own `payment_method` object.Example:
2b9e4c61-8a05-4f7d-9c33-1e6b0d5a82f4
- Two different 422 envelopes come out of this one endpoint. A bad `cadence` returns the stock validation shape — `message` plus an `errors` map keyed by field — while a bad `shipping_address_id` or `payment_method_id` returns the bespoke `success`/`error`/`message` shape shown above. Branch on the presence of `errors`, not on the status code.
- The stock validation envelope only appears if you send `Accept: application/json`. The application registers no custom exception rendering, so without that header the failure is treated as a browser form post and answered with a redirect.
- Changing cadence resets the billing anniversary. `next_charge_at` is recomputed as *now* plus one new interval, discarding whatever date was scheduled. Sending the cadence the subscription already has is a no-op — no date change and no audit event.
- Updates are applied in order — cadence, then address, then card — and are not wrapped in a transaction. A request carrying a valid `cadence` and an invalid `shipping_address_id` returns 422 with the cadence change **already committed**.
- Both ids are UUIDs scoped to `subscription.customer_id`. Discover them in v1: every address object carries `address_id`, and this resource's `payment_method` carries `payment_method_id`. A value that belongs to a different customer is a 422, not a cross-customer update.
- Soft-deleted addresses and cards are excluded by their models' global scopes, so an id the customer has since removed returns the not-found 422 rather than silently rebilling to it.
curl -X PATCH https://api.firearmcart.com/v1/subscriptions/9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31 \
-H "Authorization: Bearer $FIREARMCART_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"cadence": "quarterly"}'{
"data": {
"uuid": "9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31",
"subscription_id": 1042,
"status": "active",
"cadence": "quarterly",
"cadence_label": "Every 3 months",
"discount_pct": 10,
"next_charge_at": "2026-11-11T09:15:44+00:00",
"last_charged_at": "2026-08-01T14:00:00+00:00",
"failed_charge_count": 0,
"customer_id": 1187,
"items": [
{
"product_id": 2043,
"variant_id": 5581,
"quantity": 2,
"unit_price": 24.99
}
],
"shipping_address": {
"address_id": "6e1d9f27-3c4b-4a85-b1e0-5d8c2f7a94b3",
"type": "shipping",
"address_line1": "418 Ridgeline Dr",
"address_line2": null,
"city": "Bozeman",
"state": "MT",
"zip_code": "59718",
"is_billing": false,
"is_shipping": true,
"is_default_billing": false,
"is_default_shipping": true
},
"payment_method": {
"payment_method_id": "2b9e4c61-8a05-4f7d-9c33-1e6b0d5a82f4",
"brand": "visa",
"last_four": "4242"
},
"created_at": "2026-03-14T09:22:07+00:00",
"updated_at": "2026-08-11T09:15:44+00:00"
}
}{
"success": false,
"error": "address_not_found",
"message": "Address not found for this subscription customer."
}{
"error": "not_found",
"message": "Subscription not found."
}Pause a subscription
/v1/subscriptions/{uuid}/pause- Required ability
subscriptions:write- Rate limit
- 60 requests/minute per team
Path parameters
uuidstringrequired- The subscription's `uuid`.Example:
9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31
- **Silent no-op outside `active`.** `ReloadService::pauseSubscription()` returns early unless the current status is `active`, and the controller responds 200 regardless. Pausing an already-paused, `past_due` or `cancelled` subscription looks identical to success — confirm by reading `data.status` in the response.
- The pause is always open-ended. The API passes no until-date, so `paused_until` stays null and nothing auto-resumes; call `/resume` explicitly. (`paused_until` is not in the response either, so a dashboard-scheduled pause is invisible here.)
curl -X POST https://api.firearmcart.com/v1/subscriptions/9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31/pause \
-H "Authorization: Bearer $FIREARMCART_TOKEN" \
-H "Accept: application/json"{
"data": {
"uuid": "9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31",
"subscription_id": 1042,
"status": "paused",
"cadence": "monthly",
"cadence_label": "Monthly",
"discount_pct": 10,
"next_charge_at": "2026-09-01T14:00:00+00:00",
"last_charged_at": "2026-08-01T14:00:00+00:00",
"failed_charge_count": 0,
"customer_id": 1187,
"items": [
{
"product_id": 2043,
"variant_id": 5581,
"quantity": 2,
"unit_price": 24.99
}
],
"shipping_address": {
"address_id": "6e1d9f27-3c4b-4a85-b1e0-5d8c2f7a94b3",
"type": "shipping",
"address_line1": "418 Ridgeline Dr",
"address_line2": null,
"city": "Bozeman",
"state": "MT",
"zip_code": "59718",
"is_billing": false,
"is_shipping": true,
"is_default_billing": false,
"is_default_shipping": true
},
"payment_method": {
"payment_method_id": "2b9e4c61-8a05-4f7d-9c33-1e6b0d5a82f4",
"brand": "visa",
"last_four": "4242"
},
"created_at": "2026-03-14T09:22:07+00:00",
"updated_at": "2026-08-11T09:15:44+00:00"
}
}{
"error": "not_found",
"message": "Subscription not found."
}Resume a subscription
/v1/subscriptions/{uuid}/resume- Required ability
subscriptions:write- Rate limit
- 60 requests/minute per team
Path parameters
uuidstringrequired- The subscription's `uuid`.Example:
9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31
- **Silent no-op outside `paused` and `past_due`.** Resuming an already-active subscription changes nothing, and `cancelled` is terminal for this endpoint — v1 exposes no way to revive a cancelled subscription, which is a dashboard-only action.
- If `next_charge_at` is null or already in the past, it is rewritten to now plus one cadence interval, so a long-paused subscription is not immediately billed for the cycles it missed.
- Resuming also zeroes `failed_charge_count` and clears the internal decline type — dunning starts over from a clean slate.
curl -X POST https://api.firearmcart.com/v1/subscriptions/9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31/resume \
-H "Authorization: Bearer $FIREARMCART_TOKEN" \
-H "Accept: application/json"{
"data": {
"uuid": "9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31",
"subscription_id": 1042,
"status": "active",
"cadence": "monthly",
"cadence_label": "Monthly",
"discount_pct": 10,
"next_charge_at": "2026-09-11T09:15:44+00:00",
"last_charged_at": "2026-08-01T14:00:00+00:00",
"failed_charge_count": 0,
"customer_id": 1187,
"items": [
{
"product_id": 2043,
"variant_id": 5581,
"quantity": 2,
"unit_price": 24.99
}
],
"shipping_address": {
"address_id": "6e1d9f27-3c4b-4a85-b1e0-5d8c2f7a94b3",
"type": "shipping",
"address_line1": "418 Ridgeline Dr",
"address_line2": null,
"city": "Bozeman",
"state": "MT",
"zip_code": "59718",
"is_billing": false,
"is_shipping": true,
"is_default_billing": false,
"is_default_shipping": true
},
"payment_method": {
"payment_method_id": "2b9e4c61-8a05-4f7d-9c33-1e6b0d5a82f4",
"brand": "visa",
"last_four": "4242"
},
"created_at": "2026-03-14T09:22:07+00:00",
"updated_at": "2026-08-11T09:15:44+00:00"
}
}{
"error": "not_found",
"message": "Subscription not found."
}Skip the next cycle
/v1/subscriptions/{uuid}/skip- Required ability
subscriptions:write- Rate limit
- 60 requests/minute per team
Path parameters
uuidstringrequired- The subscription's `uuid`.Example:
9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31
- **Silent no-op outside `active`.** A paused, past-due or cancelled subscription returns 200 with an unchanged `next_charge_at`. Compare the returned date against the one you sent from.
- Skips stack. The new date is computed from the *existing* `next_charge_at`, so calling this twice defers two cycles. There is no un-skip; correcting an accidental double skip means moving the date from the dashboard.
- The offset is calendar-month arithmetic (1, 3, 6 or 12 months), not a fixed number of days, and it preserves the time of day.
curl -X POST https://api.firearmcart.com/v1/subscriptions/9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31/skip \
-H "Authorization: Bearer $FIREARMCART_TOKEN" \
-H "Accept: application/json"{
"data": {
"uuid": "9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31",
"subscription_id": 1042,
"status": "active",
"cadence": "monthly",
"cadence_label": "Monthly",
"discount_pct": 10,
"next_charge_at": "2026-10-01T14:00:00+00:00",
"last_charged_at": "2026-08-01T14:00:00+00:00",
"failed_charge_count": 0,
"customer_id": 1187,
"items": [
{
"product_id": 2043,
"variant_id": 5581,
"quantity": 2,
"unit_price": 24.99
}
],
"shipping_address": {
"address_id": "6e1d9f27-3c4b-4a85-b1e0-5d8c2f7a94b3",
"type": "shipping",
"address_line1": "418 Ridgeline Dr",
"address_line2": null,
"city": "Bozeman",
"state": "MT",
"zip_code": "59718",
"is_billing": false,
"is_shipping": true,
"is_default_billing": false,
"is_default_shipping": true
},
"payment_method": {
"payment_method_id": "2b9e4c61-8a05-4f7d-9c33-1e6b0d5a82f4",
"brand": "visa",
"last_four": "4242"
},
"created_at": "2026-03-14T09:22:07+00:00",
"updated_at": "2026-08-11T09:15:44+00:00"
}
}{
"error": "not_found",
"message": "Subscription not found."
}Cancel a subscription
/v1/subscriptions/{uuid}/cancel- Required ability
subscriptions:write- Rate limit
- 60 requests/minute per team
Path parameters
uuidstringrequired- The subscription's `uuid`.Example:
9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31
Body parameters
reasonstringoptional- Free-text cancellation reason stored on the subscription and its audit event. Keep it under 255 characters — the column is `varchar(255)` and the value is not validated before insert.Example:
Customer requested by phone
- **Silent no-op on an already-cancelled subscription.** Only `active`, `paused` and `past_due` are cancellable; a repeat call returns 200 and leaves the original `cancelled_at` and reason intact, so cancel is effectively idempotent but never tells you which call did the work.
- Cancellation is one-way through this API. There is no reactivate endpoint — bringing a cancelled subscription back is a dashboard action, and `/resume` will not do it.
- `reason` is read straight off the request with no validation rule. A string longer than 255 characters is rejected by the database, not by the validator, and surfaces as a 500 with the subscription left uncancelled.
- Neither `cancelled_at` nor `cancellation_reason` appears in `SubscriptionResource`, so you cannot read back what you just stored. Keep your own record if you need it.
curl -X POST https://api.firearmcart.com/v1/subscriptions/9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31/cancel \
-H "Authorization: Bearer $FIREARMCART_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"reason": "Customer requested by phone"}'{
"data": {
"uuid": "9f1c2b4e-6d3a-4f58-9c1b-2a7e5d0f8b31",
"subscription_id": 1042,
"status": "cancelled",
"cadence": "monthly",
"cadence_label": "Monthly",
"discount_pct": 10,
"next_charge_at": null,
"last_charged_at": "2026-08-01T14:00:00+00:00",
"failed_charge_count": 0,
"customer_id": 1187,
"items": [
{
"product_id": 2043,
"variant_id": 5581,
"quantity": 2,
"unit_price": 24.99
}
],
"shipping_address": {
"address_id": "6e1d9f27-3c4b-4a85-b1e0-5d8c2f7a94b3",
"type": "shipping",
"address_line1": "418 Ridgeline Dr",
"address_line2": null,
"city": "Bozeman",
"state": "MT",
"zip_code": "59718",
"is_billing": false,
"is_shipping": true,
"is_default_billing": false,
"is_default_shipping": true
},
"payment_method": {
"payment_method_id": "2b9e4c61-8a05-4f7d-9c33-1e6b0d5a82f4",
"brand": "visa",
"last_four": "4242"
},
"created_at": "2026-03-14T09:22:07+00:00",
"updated_at": "2026-08-11T09:15:44+00:00"
}
}{
"error": "not_found",
"message": "Subscription not found."
}
