pass.holder_stranded

A pass holder's window was cancelled with no replacement available, so their pass ended and a refund is owed.

When this fires

One holder of a cancelled access window could not be moved anywhere, so their pass was ended. Fires once per stranded holder of an ordinary pass, alongside the single pass.window_cancelled for the window itself. A season-ticket holder never reaches this state — cancelling one leg of a season emits pass_series.leg_dropped instead and leaves the rest of the slate intact.

They have paid for a date that is not happening and received nothing. Subscriby tells them so and asks them to contact the creator — it does not issue a refund.

This is the durable record of who is owed money

The creator's dashboard shows the refund count once, in a toast that survives a single page load, and the ended subscriptions are afterwards indistinguishable from ordinary expiries. This event carries the identity, the amount and the gateway reference, so consuming it is the only reliable way to reconcile refunds automatically.

Why a replacement can be missing

  • The plan has no later window scheduled at all.
  • The only later windows are already inside the plan's sales cutoff, so they are closed to sales and cannot take new holders — a later date can be visible on the calendar and still not qualify.
  • The customer already holds a pass for every remaining window.
  • The plan's repeating schedule has passed its recurrence end date, so no later window qualifies even if the calendar still shows dates.

Required ability

project-subscription:view — token must carry this at mint time to subscribe an endpoint to this event.

Payload

{
  "id": "evt_01HX...",
  "type": "pass.holder_stranded",
  "created_at": "2026-09-18T09:14:22Z",
  "api_version": "2026-05-01",
  "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
  "data": {
    "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
    "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
    "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
    "from_window_id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
    "from_starts_at": "2026-09-20T13:00:00+00:00",
    "from_ends_at": "2026-09-20T19:00:00+00:00",
    "refund_due": true,
    "amount_paid": "15.000",
    "currency": "GBP",
    "payment_id": "pi_3U9Jan4m40lWsKma0f3ntmnl"
  }
}

Field reference

FieldTypeNotes
idstring ULIDUnique event id, prefixed evt_. Use for idempotent processing.
typestringAlways pass.holder_stranded for this event.
created_atISO 8601 timestampServer-side emission time.
api_versionstringWebhook API contract version.
project_idstring UUIDProject this event belongs to.
data.subscription_idstring UUIDThe pass purchase that ended.
data.subscriber_idstring UUIDThe subscriber owed a refund.
data.plan_idstring UUIDThe pass plan.
data.from_window_idstring UUIDThe cancelled window they held.
data.from_starts_atISO 8601 timestampCancelled window start, always UTC.
data.from_ends_atISO 8601 timestampCancelled window end, always UTC.
data.refund_duebooleanAlways true. Present so a single handler can branch on it.
data.amount_paidstring decimalWhat they paid for the window. A string to preserve precision.
data.currencystringISO 4217 code, e.g. GBP. Null if the subscription has no currency recorded.
data.payment_idstringThe gateway's own reference, for issuing the refund. Null when none was recorded.

Caveats

  • The subscription also emits subscription.expired, and member.churned when it was their last active subscription. De-duplicate if you consume several.
  • No subscription.refunded follows unless the creator actually issues the refund in their payment provider, at which point the gateway's webhook records it.
  • Holders who were paused, past due, or had already cancelled their own pass are not included, even though they may also have paid. Reconcile those separately.
  • amount_paid is what the subscription recorded at purchase; it does not account for any partial refund already issued.

How is this guide?

On this page

Subscriby is a product designed by you — for you.

No boardroom full of executives deciding what we ships next. Our roadmap always shaped by you with your feedback.

Share feedback or a request