Skip to main content
POST
Calling this endpoint with an empty body (or no body at all) cancels the subscription right away, changing its status to CANCELED. This is unchanged and still final: once immediate, it cannot be reverted. You can cancel from CREATED, ACTIVE, TRIALING, PAST_DUE and PAUSED. COMPLETED and CANCELED are terminal, so canceling from either returns 400 INVALID_STATE — including a second cancel on a subscription that is already canceled. See Subscription Status.

Refund on immediate cancel

Allowlisted organizations onlyRefund quoting is gated per organization, independently of scheduled cancellation. If your calls return 400 "Refund quote is not enabled for this organization", contact your Yuno representative to have it enabled.
Send a refund mode alongside an immediate cancel (an absent schedule) to have Yuno compute a refund quote for the current billing cycle. Yuno only computes the quote — it never moves money. refund.execution on the response is always "MERCHANT": you execute the refund yourself against your own payment rail, using the quoted amount as input.
Cancel with a prorated refund
refund cannot be combined with schedule — sending both, or sending refund together with "schedule": null, is rejected with 400 before anything is written. refund: NONE, or omitting refund entirely, still works normally alongside schedule.

The refund basis

Every refund mode is computed against the same basis: the most recently captured payment on the subscription — never the subscription’s own list price, and never an estimate. If the current cycle has no captured payment at all (a decline, a payment still pending, or a gap), PRORATED, FULL, and CUSTOM all return 400 REFUND_NOT_AVAILABLE — except a genuine $0 phase (a trial or promotional phase with nothing charged), which returns 200 with amount: 0.00. There’s nothing to refund there, but that’s not an error. A PAST_DUE subscription has no captured payment for the cycle in progress, so the same rule applies: refund: NONE (or an absent refund) still cancels normally, but any other mode returns 400 REFUND_NOT_AVAILABLE with current_status: "PAST_DUE".

PRORATED

Refunds the unused days of the current cycle, using calendar-date arithmetic — never hours or minutes:
  • period_start — the date the last captured payment was charged.
  • period_end — the date the current cycle naturally ends, capped at availability.finish_at when the subscription has one and it falls earlier.
  • unused_days = period_days − used_days, where used_days counts the day you cancel on as a full used day — canceling at any time on day 10 of a 30-day cycle still counts 10 used days.
  • amount = charged_amount × unused_days / period_days, rounded HALF_UP at the currency’s minor units.
For example, a 30-day cycle charged $30.00, canceled on day 10: 10 days used, 20 days unused, amount = 30.00 × 20/30 = 20.00.
Cancel with a prorated refund — response
A subscription billed by the hour or minute has no meaningful notion of a “day,” so PRORATED returns 400 "proration is not available for sub-daily cadences" there. FULL and CUSTOM are unaffected — both still work on a sub-daily cadence.

FULL

Refunds the entire basis.charged_amount of the current cycle — amount always equals basis.charged_amount exactly, and unused_days equals period_days (the whole cycle is treated as unused).

CUSTOM

Provisional — semantics under product reviewCUSTOM’s current behavior is a merchant-supplied refund_amount sent on the cancel request itself, capped at the current cycle’s charged amount. Product is reviewing whether the refund rule for CUSTOM should instead live on the plan as a standing rule, rather than a per-cancel amount. Treat everything in this subsection as unstable until that’s resolved.
Send refund_amount alongside "refund": "CUSTOM" to refund a specific amount instead of a computed one:
Cancel with a custom refund amount
amount in the response is your refund_amount echoed back exactly — not recomputed or rounded again. refund_amount.value must be greater than 0 and must not exceed the current cycle’s charged amount, and refund_amount.currency must match the subscription’s own currency.

Reading the refund object

refund is null when refund was NONE or omitted. Otherwise:

Where refund appears

  • The cancel 200 response always carries the refund key — null when no quote was computed, the object otherwise.
  • GET /v1/subscriptions/{id} and GET /v1/subscriptions?merchant_reference=... carry the last computed refund too, once one exists — canceling with a refund quote persists it, so it keeps showing up on every later read of that subscription through either of these.
  • GET /v1/subscriptions (the paginated list) does not carry refund on any entry, whether or not that subscription was canceled with a quote — the list item is a smaller summary shape than the full subscription object, and refund isn’t one of the fields it includes.
  • The subscription.cancel webhook carries refund only when a quote was actually computed (PRORATED/FULL/CUSTOM) — it’s absent, not null, for a NONE/absent-refund cancellation.

Scheduling a cancellation instead

Allowlisted organizations onlyScheduled cancellation is gated per organization. If your calls return 400 "Scheduled cancellation is not enabled for this organization", contact your Yuno representative to have it enabled.
Send a schedule object to defer the cancellation instead of applying it now. The subscription stays in its current status — billing continues normally — until the schedule fires.
Schedule after 3 more billing cycles
Schedule for a specific date
schedule takes exactly one of: Sending both or neither returns 400. A PIX_AUTOMATIC subscription billed with frequency.execution: MERCHANT cannot schedule a cancellation — schedule it as at or after_cycles on a different payment method type, or cancel immediately instead.

Behavior while retries are running

past_due_behavior is echoed on cancel_scheduled, pending product confirmationThe engine currently stamps whatever past_due_behavior resolved for the schedule (explicit value, or the EXHAUST_RETRIES default) onto the cancel_scheduled.past_due_behavior field in every response. Treat this echo as provisional until product confirms it as the intended external contract — it may change.
past_due_behavior controls what a scheduled cancellation does if the subscription is PAST_DUE when the schedule would otherwise fire:
Schedule and skip retries if PAST_DUE when it fires
Independently of past_due_behavior, canceling a PAST_DUE subscription — whether immediately or because a schedule became due — never errors and always stops that cycle’s retries. See Subscription Status and Retries.
Refund handling is only available on an immediate cancel — see Refund on immediate cancel. It does not ship with scheduled cancellation: a schedule request cannot also carry a refund mode.

Undoing a scheduled cancellation

Send "schedule": null to clear a pending schedule. The subscription is unaffected otherwise — no status change, no charge.
Undo a scheduled cancellation
Sending "schedule": null when nothing is scheduled is a no-op: 200, cancel_scheduled stays null, and no webhook is sent. When a schedule is cleared, subscription.cancel_schedule_canceled fires instead.

Reading the result

The response carries the same Subscription shape as every other subscription endpoint. Four fields are relevant here:
  • cancel_schedulednull when no cancellation is pending, otherwise the schedule’s mode, after_cycles/at, requested_at and past_due_behavior.
  • retries.stopped, retries.attempts_made, retries.outcome, retries.next_retry_at — populated whenever the subscription is PAST_DUE or has a cancel_scheduled pending; omitted otherwise.
  • unpaid_cycle — present when the current billing cycle is PAST_DUE and has not settled.
  • refundnull (or absent on non-cancel reads) when no refund quote was computed, otherwise the quoted amount and its basis. See Refund on immediate cancel.
Persistence of retries and unpaid_cycle after cancellation is pending product confirmationBoth fields are computed from the subscription’s live state at request time. Whether a GET /v1/subscriptions/{id} issued after the subscription reaches CANCELED continues to surface the retry snapshot / unpaid cycle from the cycle that was in flight, or omits them once terminal, is not yet confirmed as a stable contract — verify against a live response before depending on it.
See the Subscription object for the full field reference.

Webhooks

  • subscription.cancel_scheduled — sent when a cancellation is scheduled via this endpoint.
  • subscription.cancel_schedule_canceled — sent when a pending scheduled cancellation is undone via "schedule": null.
An immediate cancellation (empty body, or a schedule becoming due) still emits subscription.cancel as before — scheduling emits its own events only for the scheduling and undoing actions themselves. subscription.cancel’s payload carries refund too, following the same rule as the cancel response itself: present only when a quote was actually computed (PRORATED/FULL/CUSTOM), absent for a NONE/absent-refund cancellation.

Errors

Authorizations

public-api-key
string
header
default:<Your public-api-key>
required
private-secret-key
string
header
default:<Your private-secret-key>
required

Path Parameters

subscription_id
string
required

The unique identifier of a subscription.

Body

application/json
refund
string

NONE (default), PRORATED, FULL, or CUSTOM. Computes a refund quote for the current billing cycle on an immediate cancel. Cannot be combined with schedule.

Example:

"PRORATED"

refund_amount
object

Required, and only allowed, when refund is CUSTOM. Must not exceed the current cycle's charged amount.

schedule
object | null

Response

200

id
string
Example:

"7304911d-5df9-429e-8488-ad41abea1a4c"

name
string
Example:

"sub_001"

description
string | null
Example:

"streaming service"

account_id
string
Example:

"2404911d-5df9-429e-8488-ad41abea1a4b"

merchant_reference
string
Example:

"001_marzo_23"

status
string
Example:

"CANCELED"

subscription_plan_id
string
Example:

"1904911d-5df9-429e-8488-ad41abea1a4d"

amount
object
frequency
object
billing_cycles
object
customer_payer
object
payment_method
object

The payment method the subscription charges. A single object, not a list.

availability
object
metadata
object | null
payments
string[]
retries
object
unpaid_cycle
object

Present only when the current billing cycle is PAST_DUE and has not settled.

cancel_scheduled
object | null

null when no cancellation is pending.

refund
object | null

null when refund was NONE or omitted. Present on the cancel response and on every later read once computed.

created_at
string
Example:

"2023-12-16T20:46:54.786342Z"

updated_at
string
Example:

"2023-12-16T21:00:54.786342Z"