Skip to main content

Cancel Subscription

Cancel a subscription in your store.

The request is synchronous — the response already reflects the new status, cancel_at, and canceled_at.

Two modes

The endpoint has two behaviours, controlled by the optional immediately flag in the body:

  • Omitted (or false/null) — use the default auto-pick:
    • Healthy subscription: cancel at the end of the current period. The customer keeps access until current_period_end.
    • past_due subscription: cancel immediately. There is no period-end grace for an unpaid subscription.
  • immediately: true — force an immediate cancel even on a healthy subscription. The customer loses access right away.

Read the returned cancel_at / canceled_at to confirm which mode applied.

The read response's is_cancelable boolean tells you in advance whether a cancel would succeed — see Get subscription.

Request

POST /subscriptions/{id}/cancel

Path Parameters

ParameterTypeRequiredDescription
idstringYesSubscription UUID

Request Body

ParameterTypeRequiredDefaultDescription
immediatelybooleanNofalseForce an immediate cancel even on a healthy subscription. Omit (or send false/null) to use the auto-pick.

Example Request — auto-pick (period-end or immediate for past_due)

curl -X POST "https://cart.easy.tools/api/v1/subscriptions/550e8400-e29b-41d4-a716-446655440040/cancel" \
-H "Authorization: Bearer YOUR_API_TOKEN"

Example Request — force immediate cancel

curl -X POST "https://cart.easy.tools/api/v1/subscriptions/550e8400-e29b-41d4-a716-446655440040/cancel" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"immediately": true
}'

Response

Success Response (200)

Returns the updated subscription (base fields only; no include sections).

Healthy subscription cancelled at period end

{
"id": "550e8400-e29b-41d4-a716-446655440040",
"remote_id": "sub_1QabcDEFghiJKLmn",
"provider": "stripe",
"status": "active",
"variant_name": "Monthly Plan",
"product_name": "Premium Course",
"recurring_amount": 4900,
"currency": "pln",
"interval": "month",
"interval_count": 1,
"quantity": 1,
"customer_email": "buyer@example.com",
"current_period_start": "2026-05-20T14:02:00+00:00",
"current_period_end": "2026-06-20T14:02:00+00:00",
"trial_end": null,
"cancel_at": "2026-06-20T14:02:00+00:00",
"canceled_at": "2026-05-28T12:00:00+00:00",
"active_until": null,
"active_cycles": null,
"cancel_early": false,
"keep_access_after_expiring": false,
"is_delegated": false,
"is_cancelable": false,
"created_at": "2026-01-15T10:00:00+00:00",
"customer": null,
"variant": null,
"product": null,
"order": null,
"renewals": null,
"upcoming_invoice": null
}

Immediate cancel (immediately: true or past_due)

{
"id": "550e8400-e29b-41d4-a716-446655440040",
"status": "canceled",
"cancel_at": "2026-05-28T12:00:00+00:00",
"canceled_at": "2026-05-28T12:00:00+00:00",
"is_cancelable": false,
"...": "(other fields as above)"
}

See the Get Subscription reference for a full description of each base field.

Error Responses

Bad Request (400)

Returned when the path parameter is not a valid UUID.

{
"message": "Invalid subscription ID"
}

Subscription Not Found (404)

{
"message": "Subscription with ID 550e8400-e29b-41d4-a716-446655440040 not found"
}

Subscription Cannot Be Canceled (422)

Returned when the subscription is not in a cancelable state — for example it has already been canceled or it is a fixed-cycles plan with cancel_early=false.

{
"message": "Subscription cannot be canceled in its current state."
}

Provider Error (422)

Returned when the payment provider rejects the cancel.

{
"message": "Payment provider rejected the cancellation: subscription is already canceled"
}

Validation Error (422 Unprocessable Entity)

Returned when immediately is present but not a boolean.

{
"message": "The given data was invalid.",
"errors": {
"immediately": [
"The immediately field must be true or false."
]
}
}

Unauthorized (401)

{
"message": "Unauthenticated."
}