{
    "openapi": "3.1.2",
    "info": {
        "title": "Subscriby REST API",
        "version": "1.0.0",
        "description": "Everything the creator dashboard can do, over HTTPS at `https://api.subscriby.net/v1`: projects, plans, members, subscriptions, payment methods, coupons, access codes, broadcasts, support, connectors, disaster recovery, teams, tokens and webhooks. Every write runs the same action the dashboard and the MCP server run, so the three surfaces never disagree about what happened.\n\n## Authentication\n\nEvery request carries a personal access token as a bearer, `Authorization: Bearer sbt_live_…`. Tokens are minted on the dashboard under **Settings → Tokens**, carry an explicit list of abilities, and are frozen to one team at mint time; each operation below names the ability it requires under **Requires ability**. A `sbt_test_` token is refused on production. Read the [authentication guide](https://docs.subscriby.net/api/v1/authentication), the [ability catalogue](https://docs.subscriby.net/api/v1/abilities) and [how team and project scopes combine](https://docs.subscriby.net/api/v1/tenancy-and-scopes).\n\n## Writes are idempotent\n\nEvery `POST`, `PATCH`, `PUT` and `DELETE` requires an `Idempotency-Key` header. The same key replays the original 2xx response for 24 hours with `Idempotent-Replay: true`, so a retry after a timeout never repeats the write; the same key with a different body is refused with `409 IDEMPOTENCY_KEY_REUSED`. See [idempotency](https://docs.subscriby.net/api/v1/idempotency).\n\n## Errors\n\nEvery failure answers with one envelope, `{ \"error\": { \"code\", \"message\", \"docs_url\", \"remediation\", \"request_id\", \"fields\"?, \"context\"? } }`. Branch on `error.code`; `message` may be reworded. The codes every endpoint can answer are documented once on the shared responses below, and an endpoint with a failure of its own lists it. The full catalogue is on the [error reference](https://docs.subscriby.net/api/v1/errors).\n\n## Lists\n\nA list answers `{ \"data\": [...], \"links\": {...}, \"meta\": {...} }`, newest first, paged by `page` and `per_page` (capped at 100). Each list documents its own default page size and filters. See [pagination](https://docs.subscriby.net/api/v1/pagination).\n\n## Rate limits\n\nA token may make 300 requests a minute and 10,000 an hour; `429 RATE_LIMITED` carries `Retry-After`. Two endpoints have tighter buckets of their own and say so. See [rate limiting](https://docs.subscriby.net/api/v1/rate-limiting).\n\n## Identifiers\n\nEvery resource id is a bare UUID with no type prefix; the field name says what it points at. Two exceptions are documented where they appear: a webhook envelope's `evt_` ULID and a personal access token's integer id.\n\n## Other ways in\n\nThe [MCP server](https://docs.subscriby.net/mcp/v1) exposes the same operations as tools for agent runtimes, and each endpoint below names the tools that wrap it under **MCP tools**. [Zapier](https://docs.subscriby.net/integrations/zapier) and [n8n](https://docs.subscriby.net/integrations/n8n) call these endpoints for you."
    },
    "servers": [
        {
            "url": "https://api.subscriby.net",
            "description": "Production"
        }
    ],
    "tags": [
        {
            "name": "Ping",
            "description": "The one endpoint that needs no token. It answers from the API host itself, so a `200` proves the host resolves, TLS terminates and the application is up; it says nothing about your token, which `GET /v1/teams/current` is the probe for."
        },
        {
            "name": "Activity",
            "description": "Every mutation Subscriby performs, whether from the dashboard, the REST API, an MCP tool call, a Zapier step or a scheduled system task, is recorded against its subject in the activity log. `GET /v1/activity` returns that log filtered to a single subject so agents and audit tools can reconstruct exactly what changed and who did it.\n\n## Related\n\n- [Actor kind](https://docs.subscriby.net/reference/glossary#actor-kind) in the glossary."
        },
        {
            "name": "Analytics",
            "description": "Read-only analytics under `/v1/analytics/*` surface the same figures the creator dashboard renders. Every endpoint delegates to the same service layer the dashboard uses, so the dashboard, the MCP tools and REST callers see identical numbers.\n\nAll eight reads are tenant-scoped by the token's team, need no `Idempotency-Key`, and share the token's general rate limit.\n\n## Common query parameters\n\nMost reads share the same window selection:\n\n- `period`: a preset window, one of `7d`, `14d`, `30d`, `60d`, `90d`, `mtd`, `qtd`, `ytd`, `1y`, `all`. Defaults to `30d`. Ignored when both `from` and `to` are supplied; an unknown value falls back to the default rather than failing.\n- `from`, `to`: an explicit `YYYY-MM-DD` range. Takes precedence over `period` when both ends are provided.\n- `project_id`: an optional project id. Scopes the response to a single project; omit for every project visible to the token. A project outside the token's `scope:project:` allow-list is `404 TENANT_MISMATCH`, an unknown one `404 RESOURCE_NOT_FOUND`.\n\nThe dashboard, earnings and transaction-breakdown reads additionally accept filter allow-lists: `plan_ids`, `statuses`, `payment_method_ids`. Pass each as an array (`?plan_ids[]=uuid1&plan_ids[]=uuid2`) or as one comma-separated string (`?plan_ids=uuid1,uuid2`).\n\n## Caching\n\nAll reads share the same 5-minute cache the creator dashboard uses. A REST call warms the human-facing view and vice versa; consecutive calls with identical filters hit the cache until it rotates.\n\n> The service layer returns USD-normalised totals for cross-currency comparability. Per-plan or per-payment rows still carry their original currency alongside the USD-normalised amount.\n\n## Related\n\n- [Ability catalogue](https://docs.subscriby.net/api/v1/abilities)\n- [Rate limiting](https://docs.subscriby.net/api/v1/rate-limiting)\n- [Errors](https://docs.subscriby.net/api/v1/errors)"
        },
        {
            "name": "Groups",
            "description": "A **group** is a named bundle of permissions on a team that several collaborators hold at once: put the three people who run the inbox into a `Support` group and they share its permissions, take one out and they keep only what their own role gives them. Groups sit beside [roles](https://docs.subscriby.net/api/v1/reference/roles), which are assigned one per collaborator; a group is the way to grant the same extra permissions to a set of people without editing each role.\n\nEach group carries `permissions`, the exact ability strings a token can hold, and `member_ids`, the collaborators in it. Both are returned when a group is read individually or after a write and omitted from the list so a listing stays one query. Membership is replaced as a whole with `PUT …/members`, so a sync from your own directory sends the full list each time rather than adding and removing one by one. Deleting a group removes what it granted from everyone in it; nobody leaves the team.\n\nVisibility is the union of every team the caller owns or belongs to, and a group on a team outside that set answers `404 RESOURCE_NOT_FOUND` rather than `403`, so the API never confirms that a team exists. Every write announces itself as a `group.*` event.\n\n## Related\n\n- [Teams](https://docs.subscriby.net/api/v1/reference/teams)\n- [Roles](https://docs.subscriby.net/api/v1/reference/roles): per-collaborator permission sets\n- [Team Members](https://docs.subscriby.net/api/v1/reference/team-members)\n- [`group.*` webhook events](https://docs.subscriby.net/webhooks/v1/events/group)"
        },
        {
            "name": "Projects",
            "description": "A **project** is the container for one membership business: its plans, its members and their subscriptions, its payment methods, the resources a purchase unlocks and the connectors it runs on. A team can hold several, each with its own portal at a `handle` of its choosing, its own terms and privacy links, artwork and public-metrics switch. A project has no platform of its own: it installs [connectors](https://docs.subscriby.net/api/v1/reference/connectors), and the places those connectors gate become its resources.\n\nThe endpoints create, read, update and delete projects, and offer **archive** and **restore** as actions separate from update. Archiving flips `active` off so the portal stops selling while every plan, member and payment method is kept; restoring switches it back on. Delete removes the project and everything under it, so prefer archiving to pause intake without losing history. A custom `handle` needs the account tier that unlocks it, and changing it moves the portal URL at once.\n\nA token minted with `scope:project` entries sees only those projects, and any project outside the token's team or scope is a `404 RESOURCE_NOT_FOUND`. Every change announces itself as a `project.*` event; connecting and disconnecting a connector emits `connector.*` events from their own flows rather than from here.\n\n## Related\n\n- [Plans](https://docs.subscriby.net/api/v1/reference/plans)\n- [Connectors](https://docs.subscriby.net/api/v1/reference/connectors): the platforms a project runs on.\n- [Ability catalog](https://docs.subscriby.net/api/v1/abilities)\n- [Webhook Events](https://docs.subscriby.net/api/v1/reference/webhook-events)\n- [`project.*` webhook events](https://docs.subscriby.net/webhooks/v1/events/project): what the endpoints below announce; `connector.connected` and `connector.disconnected` come from the connect and disconnect flows, not from here."
        },
        {
            "name": "Distribution",
            "description": "Every project exposes two public URLs: the subscriber portal and the deep link into the project's connector installation, with a start payload that decides what opens. These endpoints return the canonical strings so clients do not reconstruct them from project, installation and plan fields themselves; if the URL shapes ever change, REST callers get the update for free. The connector shapes its own links; nothing here spells a platform's URL.\n\n## Related\n\n- [Connectors](https://docs.subscriby.net/api/v1/reference/connectors): read the installation's state before building deep links; the installation object carries its `handle`.\n- [Projects](https://docs.subscriby.net/api/v1/reference/projects): `handle` on the project resource.\n- [Creator sharing guide](https://docs.subscriby.net/creators/share)"
        },
        {
            "name": "Members",
            "description": "Members are the project-scoped subscribers. Every payment is made on behalf of a member; every access grant a connector issues resolves to one. These endpoints list and read them, flip the three moderation states (ban, unban, kick) and manage the accounts a member has connected on the connectors.\n\n## Related\n\n- [Subscriptions](https://docs.subscriby.net/api/v1/reference/subscriptions): the purchases a member holds.\n- [Support Conversations](https://docs.subscriby.net/api/v1/reference/support-inbox): a block there is an inbox decision, not a moderation one.\n- [`member.*` webhook events](https://docs.subscriby.net/webhooks/v1/events/member): the endpoints below announce `banned`, `unbanned`, `kicked` and `identity_unlinked`; `identity_linked` fires when a member connects an account, and the rest of the family (`joined`, `trial_joined`, `converted`, `churned`, `removed`, `resource_added`, `resource_pending`, `resource_removed`) comes from upstream flows."
        },
        {
            "name": "Payment Methods",
            "description": "Every project configures one or more payment providers so subscribers can buy plans. These endpoints let you read which providers a project has connected and in what mode, switch each one on or off, push the plan catalogue to its gateway again, and remove one. Entering or rotating credentials remains dashboard-only, because each provider needs its own OAuth or secret-entry flow that a generic REST layer cannot safely reproduce.\n\n## Related\n\n- [Payment provider matrix](https://docs.subscriby.net/payments)\n- [`project.*` webhook events](https://docs.subscriby.net/webhooks/v1/events/project): connecting a gateway raises no event, so the first thing an endpoint hears about a new method is its first update or its deletion; credentials never appear in a payload, and when keys are rotated from the dashboard `changes.config.keys` names **which** keys changed and nothing else."
        },
        {
            "name": "Coupons",
            "description": "A coupon is one code many subscribers can redeem for money off at checkout: the multi-redemption counterpart to an [access code](https://docs.subscriby.net/api/v1/reference/access-codes), which is one code for one person and grants access outright without a payment. Coupons live under a project at `/v1/projects/{project}/coupons`.\n\nCoupons require the **Coupons Addon**, or a Growth plan. Every write is refused with `403 TEAM_TIER_REQUIRED` if the creator is not entitled, and entitlement is re-checked again when a subscriber actually redeems.\n\n## Related\n\n- [Coupon codes in the creator guide](https://docs.subscriby.net/creators/coupon-codes): the feature walkthrough.\n- [Coupons Addon](https://docs.subscriby.net/addons/coupons): pricing, and which payment methods can discount.\n- [`coupon.*` webhooks](https://docs.subscriby.net/webhooks/v1/events/coupon): the seven events; `coupon.redeemed` fires per checkout that settles with the code and `coupon.exhausted` when the last slot under the cap is taken, neither from a call here.\n- [Access Codes](https://docs.subscriby.net/api/v1/reference/access-codes): one code, one person, grants access.\n- [Abilities](https://docs.subscriby.net/teams/abilities#project-coupon): how `project-coupon:*` maps onto team roles."
        },
        {
            "name": "Referral Program",
            "description": "A project's **Referral Program** turns members into affiliates: each gets a code and a link, a friend who arrives through them is counted for thirty days, and when that friend's first payment settles the affiliate earns what the programme promises, free membership days or a cash commission the creator pays out themselves. The programme, its affiliates, their referrals, the ledger of rewards and the payouts the creator records all live under `/v1/projects/{project}`.\n\nThe Referral Program is bundled with the **Growth** plan; Free and Starter accounts buy the **Referral Program Addon**. Every write is refused with `403 TEAM_TIER_REQUIRED` when the creator is not entitled, and a programme on a lapsed account stops attributing and earning until the addon is bought again; what affiliates already earned stays, and the reads, the payouts and the ledger keep working so they can be paid.\n\nA project holds one programme, addressed by the project alone. Rewards already written never change: each is priced when the payment settles, so editing the programme moves nothing in the ledger, and every approved or pending affiliate is told in their chat and by mail whenever the terms change, the programme is paused or it is switched back on.\n\n## Related\n\n- [Referral Program in the creator guide](https://docs.subscriby.net/creators/referral-program): the feature walkthrough.\n- [Referral Program Addon](https://docs.subscriby.net/addons/referral-program): pricing and what it unlocks.\n- [`referral.*` webhooks](https://docs.subscriby.net/webhooks/v1/events/referral): the ten events; captures, conversions, rewards and reversals fire from members' own payments and the ledger, never from a call here.\n- [Coupons](https://docs.subscriby.net/api/v1/reference/coupons): the friend reward a programme can apply at a referred friend's checkout.\n- [Members](https://docs.subscriby.net/api/v1/reference/members): the ids an affiliate and a referral name.\n- [Abilities](https://docs.subscriby.net/teams/abilities#project-referral): how `project-referral:*` maps onto team roles."
        },
        {
            "name": "Smart Links",
            "description": "A **Smart Link** is a tracked address a creator hands out per channel: one for a video description, one for a bio, one printed as a QR on a flyer. Each lives at `https://my.subscriby.net/{handle}/go/{slug}` and counts its clicks, and every member who signs in within thirty days of clicking it is credited to it, so the creator can read which channel brings leads, purchases and payments. Links live under a project at `/v1/projects/{project}/links`.\n\nSmart Links are on **every plan**, Free included. Nothing here is refused for a tier.\n\nA link carries two names. The **slug** is the address segment the creator types and may rename; the old address stops answering. The **code** is a stable seven-character string minted once; it rides in the bot deep link (`?start=via_<code>`), in the embed page's `via` and in the attribution cookie, so a printed QR and a shared bot link keep working after a rename. Archiving is the only removal: the members a link brought and what they paid stay on the funnel.\n\n## Related\n\n- [Smart Links in the creator guide](https://docs.subscriby.net/creators/smart-links): the feature walkthrough, the embeds and the funnel.\n- [`link.*` webhooks](https://docs.subscriby.net/webhooks/v1/events/link): the three events; clicks and attributions announce nothing.\n- [Members](https://docs.subscriby.net/api/v1/reference/members): every member object carries `source`, the link credited with them.\n- [Subscriptions](https://docs.subscriby.net/api/v1/reference/subscriptions): every subscription object carries the same `source`.\n- [Abilities](https://docs.subscriby.net/teams/abilities#project-link): how `project-link:*` maps onto team roles."
        },
        {
            "name": "Revenue Recovery",
            "description": "**Revenue Recovery** is what a project does when a renewal fails, when a member cancels, and after a member leaves. A failed renewal keeps the member's access for a grace window the creator sets (0 to 30 days; a new project starts at 0) while the gateway retries, with a notice at the failure, a reminder on day three, a final warning on the last day and one more when access pauses, each carrying the rail's own way to pay again; the first charge that settles restores access and counts as a recovery. A member who cancels is asked why and, where the owner's plan includes the offers, shown one offer for their rail: a pause for one billing cycle, a discount on the renewals, or a coupon to come back with. After they leave, and from the moment a lead arrives, a checkout stalls or a trial without a card nears its end, a sequence can reach them on the days the creator chose; those live under their own tag, [Recovery Sequences](#tag/recovery-sequences). Every checkout a member starts, on the portal or in a bot, is written to a ledger and counted as stalled once the project's checkout window has passed with no settled charge; the next charge that settles closes it as recovered.\n\nThe settings, the figures and the three ledgers (the cancellation screens, the activity and the checkouts) live under `/v1/projects/{project}/retention`. A project holds one row of settings, created on the first read, so the resource is addressed by the project alone.\n\nThe notices, the grace window and the cancellation question are on **every plan**. The three offers and the sequences need **Growth or the Revenue Recovery Addon**; `offers_available` on the settings says whether this project has them. The offer settings are stored on every plan and ignored by the cancellation screen without the entitlement, so switching one on early is accepted and starts working the day the plan includes it.\n\n## Related\n\n- [Revenue Recovery in the creator guide](https://docs.subscriby.net/creators/revenue-recovery): the grace window, the notice ladder with the way back per rail, the cancellation screen and the sequences.\n- [`subscription.*` webhooks](https://docs.subscriby.net/webhooks/v1/events/subscription): `subscription.payment_recovered`, `subscription.access_suspended`, `subscription.access_restored`, `subscription.cancellation_feedback` and `subscription.offer_taken` announce what the ledger records.\n- [`checkout.*` webhooks](https://docs.subscriby.net/webhooks/v1/events/checkout): `checkout.stalled` and `checkout.recovered` announce what the checkout ledger records; [`member.lead_created`](https://docs.subscriby.net/webhooks/v1/events/member) announces a new lead.\n- [Recovery Sequences](https://docs.subscriby.net/api/v1/reference/recovery-sequences): the sequences on all four triggers, their steps and the passages members make through them.\n- [Subscriptions](https://docs.subscriby.net/api/v1/reference/subscriptions): a subscription in grace or paused for non-payment keeps the `past_due` status while the gateway retries.\n- [Abilities](https://docs.subscriby.net/teams/abilities#project-subscription): the settings and the ledgers sit behind `project-subscription:*`, because they are facts about a project's subscriptions."
        },
        {
            "name": "Recovery Sequences",
            "description": "A **sequence** is the ordered set of messages a member receives on the days the creator chose after one of four moments: each step waits a number of days after the one before (the first after the trigger, 0 for the next hourly run), says what the creator wrote with `{name}`, `{project}`, `{coupon}`, `{discount}` and `{link}` filled per member, carries the way to the plan as a button and, optionally, a coupon. A member enrols once per firing, never while they hold what the trigger counts as a conversion, and leaves the sequence the moment a charge settles for them, which counts as a win on a churn sequence and a conversion on the others. Sequences live under a project at `/v1/projects/{project}/sequences`.\n\nSequences need **Growth or the Revenue Recovery Addon**. Building or changing one on a plan without them is refused as `422 VALIDATION_FAILED`; a sequence that exists when the plan lapses keeps its rows and holds every due step until the plan includes sequences again.\n\nFour triggers enrol a member: `churned` (their last live membership ended), `lead` (they arrived without buying), `stalled_checkout` (a checkout they started stayed open past the project's checkout window) and `trial_ending` (a trial without a card is about to end, the project's trial reminder before it; both windows are settings under [Revenue Recovery](#tag/revenue-recovery)). A sequence runs on one trigger; a member enters it once per firing, never while they hold what the trigger counts as a conversion, and leaves it the moment a charge settles for them. Every step carries a Stop command, and a member who pressed it stays out of every sequence until a charge settles for them or they switch the follow-ups back on in the portal.\n\n## Related\n\n- [Revenue Recovery](https://docs.subscriby.net/api/v1/reference/revenue-recovery): the settings, the figures and the two ledgers; a sequence step is a row of the activity ledger.\n- [`sequence.*` webhooks](https://docs.subscriby.net/webhooks/v1/events/sequence): the seven events, from the sequence's own lifecycle to each passage's enrolment, steps, win and exit.\n- [Coupons](https://docs.subscriby.net/api/v1/reference/coupons): a step's coupon is one of the project's own, and the member redeems it at checkout.\n- [Abilities](https://docs.subscriby.net/teams/abilities#project-sequence): how `project-sequence:*` maps onto team roles."
        },
        {
            "name": "Broadcasts",
            "description": "A broadcast sends one message, through the project's connector, to a segment of the project's members. It is a **send, not a stored record**: there is no index endpoint and no broadcast id, because nothing is persisted. What happened is reported by the [`broadcast.queued`](https://docs.subscriby.net/webhooks/v1/events/broadcast/broadcast-queued) and [`broadcast.completed`](https://docs.subscriby.net/webhooks/v1/events/broadcast/broadcast-completed) webhook events, which carry the audience and the delivery tallies.\n\n> **A broadcast cannot be recalled.** Every recipient is a real person and the message arrives in their private chat. Size the audience with the preview endpoint before you send; a segment that silently resolves to *everyone* is the one mistake this API cannot undo.\n\nThere is no separate read ability: knowing who a broadcast would reach is the same privilege as being able to reach them, so all three endpoints take `broadcast:send`.\n\n## Related\n\n- [`broadcast.*` webhook events](https://docs.subscriby.net/webhooks/v1/events/broadcast): react to sends and their outcomes.\n- [Broadcasts in the creator guide](https://docs.subscriby.net/creators/broadcasts): the same feature in the dashboard.\n- [Zapier](https://docs.subscriby.net/integrations/zapier) and [n8n](https://docs.subscriby.net/integrations/n8n): send broadcasts without writing code."
        },
        {
            "name": "Creator Tasks",
            "description": "A **creator task** is a grant no connector can give. When a purchase entitles a subscriber to a **manual** resource, a perk the creator hands over themselves, the access ledger records a `creator_task` grant in state `pending` and opens a task naming the member and the perk. The dashboard lists the open tasks on the members page; these endpoints do the same for integrations, and completing one issues the grant.\n\nNo new ability gates tasks: a task is a fact about a subscription's access, so the subscription abilities apply.\n\n## Related\n\n- [Subscriptions](https://docs.subscriby.net/api/v1/reference/subscriptions): the grants a purchase holds.\n- [Resources](https://docs.subscriby.net/api/v1/reference/resources): manual resources are created there.\n- [Webhook Events](https://docs.subscriby.net/api/v1/reference/webhook-events)\n- [`creator_task.*` webhook events](https://docs.subscriby.net/webhooks/v1/events/creator-task): `creator_task.opened` fires per manual resource when a purchase activates; completing a task raises `creator_task.completed`, then `member.resource_added`."
        },
        {
            "name": "Plans",
            "description": "A **plan** is what a project sells: the price, the currency, the billing cycle or the dated windows, the eligibility rules and the resources a purchase unlocks. Every plan has a **`kind`** that decides its whole shape. A `subscription` renews on a cycle and carries a `billing` block; a `pass` sells one dated access window per purchase and carries a `pass` block; a `pass_series` sells a slate of other pass plans' windows in one go and carries a `pass_series` block. The kind names exactly one block, and the other two are absent.\n\nA plan exists and, separately, is on sale. **Publish** and **unpublish** flip `active` and are how intake is paused while the plan stays on the books and editable; **delete** removes the row, and is refused while a customer still holds an unfinished window. A `sales_cap` pauses the plan by itself when it fills, `eligibility` narrows who may buy, `resources` are the places the plan grants, and the storefront **order** and a series' **next season** are actions of their own. Plans live under a project at `/v1/projects/{project}/plans`, and `POST` takes the same discriminated shape the reads return.\n\nEvery change announces itself as a `plan.*` event; a `kind: pass` plan also emits `pass.*` events as its windows are scheduled, open and close, and a series emits `pass_series.*` alongside them.\n\n## The shape is a discriminated union\n\n`kind` is always present, and it names **exactly one** nested object that accompanies it:\n\n| `kind`         | Carries       | Sells                                                                                   |\n| -------------- | ------------- | --------------------------------------------------------------------------------------- |\n| `subscription` | `billing`     | Access that begins at payment and renews on a cycle.                                    |\n| `pass`         | `pass`        | One dated access window per purchase.                                                   |\n| `pass_series`  | `pass_series` | A slate of *other* pass plans' windows, sold once.                                      |\n\nThe other two blocks are **absent**, not null. Presence is a consequence of the tag, never a signal in its own right: read `kind` and you know what you are holding.\n\n> **This replaced a nullable `pass` object.** The previous shape emitted `pass: null` on ordinary plans and told consumers to branch on its presence. That is a type tag smuggled in as a presence check: it cannot express a third kind, and it left every integrator inferring the rule. It also emitted `billing_cycle`, `trial_days` and `recurring` on **every** plan including passes, where they mean nothing. A field that is present and lying is worse than one that is absent, so the cycle fields now appear only on the kind that has a cycle.\n\n**Writes mirror reads exactly**, so a payload you read back is a payload you can send. The read endpoint shows one worked plan per kind, field by field.\n\n## Two axes: existence and availability\n\n`DELETE` removes the row; publish and unpublish flip `active`. Prefer unpublish for \"pause intake while keeping the plan on the books\": members who already joined keep their access either way, and an unpublished plan stays fully editable.\n\n## Related\n\n- [Projects](https://docs.subscriby.net/api/v1/reference/projects)\n- [Pass windows](https://docs.subscriby.net/api/v1/reference/pass-windows): the dated windows a pass plan generates, and how to add, cancel or nudge one.\n- [Payment methods](https://docs.subscriby.net/api/v1/reference/payment-methods)\n- [Webhook events](https://docs.subscriby.net/api/v1/reference/webhook-events)\n- [`plan.*` events](https://docs.subscriby.net/webhooks/v1/events/plan): what these endpoints announce, plus `plan.sold_out` and `plan.sync_completed`, which no call emits directly.\n- [`pass.*` events](https://docs.subscriby.net/webhooks/v1/events/pass): a `kind: pass` plan also emits these as its windows are scheduled, open and close.\n- [`pass_series.*` events](https://docs.subscriby.net/webhooks/v1/events/pass-series): a `kind: pass_series` plan emits those **and** this family describing the slate."
        },
        {
            "name": "Pass Windows",
            "description": "A **pass window** is one dated stretch of access on a [`kind: pass`](https://docs.subscriby.net/api/v1/reference/plans) plan: the Saturday 09:00–12:00 a buyer of a match-day pass actually gets. Most windows are generated from the plan's slots; a creator can also place one by hand. A pass series is a slate of these windows, so their ids are what a series points at.\n\nWindows are their own resource rather than an include on the plan: an integration authoring a series needs the ids without pulling a whole plan per source plan. The writes are the three the dashboard's **Manage Access Windows** panel offers (place a date, cancel one, nudge its holders) and they run the same actions the panel does.\n\n## Related\n\n- [Plans](https://docs.subscriby.net/api/v1/reference/plans): the `pass` and `pass_series` kinds these windows belong to, and the successor endpoint.\n- [Subscriptions](https://docs.subscriby.net/api/v1/reference/subscriptions): nudge one holder instead of a whole window.\n- [Time-limited passes guide](https://docs.subscriby.net/creators/time-limited-passes): adding a date by hand, cancelling a window, and what holders see.\n- [`pass.*` webhook events](https://docs.subscriby.net/webhooks/v1/events/pass): `pass.window_opened` and `pass.window_closed` come from the scheduler as each window's start and end pass, not from any call here."
        },
        {
            "name": "Access Codes",
            "description": "Access codes are pre-generated single-use subscription activations a creator hands out. Internally they are pending subscription rows that a subscriber redeems; redemption just claims the row. They live under the plan they activate, at `/v1/projects/{project}/plans/{plan}/access-codes`.\n\n## Related\n\n- [Creator access-code guide](https://docs.subscriby.net/creators/codes)\n- [`access_code.*` webhook events](https://docs.subscriby.net/webhooks/v1/events/access-code): `generated` once per batch when the job completes, never per code; `redeemed` per code as subscribers claim them; `expired` per code when the reaper removes an unredeemed code past its expiry.\n- [Plans](https://docs.subscriby.net/api/v1/reference/plans): the plan a code activates."
        },
        {
            "name": "Resources",
            "description": "Resources are what a plan unlocks: a place a connector gates (a channel, group or supergroup on Telegram today; each connector's own kinds as it launches) or a manually-tracked perk such as a PDF, a token or a URL. The REST API reads every resource, creates manual perks, and asks the connector to link a place; it never attaches a place itself.\n\n> **A place is linked only through its connector**, which proves the installation administers it before the resource exists. The link-request endpoint starts that conversation; the REST and MCP surfaces accept no place identifier, so a token can never attach an arbitrary place.\n\n## Related\n\n- [Connectors](https://docs.subscriby.net/api/v1/reference/connectors): each connector's `resource_kinds`, with the labels, grant mode and plan shapes of every kind.\n- [Creator resources guide](https://docs.subscriby.net/creators/resources)\n- [Webhook Events](https://docs.subscriby.net/api/v1/reference/webhook-events)\n- [`project.resource.*` events](https://docs.subscriby.net/webhooks/v1/events/project): `linked` fires when the connector finishes a link request, and `updated` also fires when a recovery swap moves the place (`changes.space_id`); the endpoints below announce their own changes."
        },
        {
            "name": "Disaster Recovery",
            "description": "Everything the **Disaster Recovery** pages show a creator is readable here: what the health probes found broken, what was done about it and whether it can still be undone, how many members a channel recovery has re-admitted so far, how many self-service recoveries the rolling window still allows, and how ready the account is for the next ban. And everything a creator does about it afterwards is here too: the per-project settings, the standbys kept ready, the two requests that start a chat picker on the connector, the undo, the reminder to stragglers, the handover mail after a bot replacement, and the member list to keep before one.\n\nThe ledger endpoints live under `/v1/recovery` with no project in the path because the ledger belongs to the **account holder**, not to a project: a ban lands on the creator's sign-in account and on every project at once. Settings and standbys hang off the project and the resource they concern. The creator's own account lives under `/v1/me/recovery`.\n\n## Tenancy\n\nThe ledger a token reads is the one of the creator who owns the team the token is scoped to. A teammate holding `project-recovery:view-any` therefore reads the same rows the owner sees on the dashboard; a token scoped to another team sees none of them, and any id from another creator's ledger is `404 RESOURCE_NOT_FOUND`.\n\n> **Reads are the team's, writes are the owner's.** The writes run the same actions the dashboard runs, and those refuse anyone but the project owner (or, for the account, the account holder) with `422 VALIDATION_FAILED` and the reason, the same sentence the dashboard would show. Registering a standby installation and replacing the project bot take a credential and stay off tokens altogether.\n\nEvery enum value comes with its label beside it (`kind_label`, `status_label`, `reason_label`), the same words the dashboard shows, so a client can render the ledger without a translation table of its own.\n\n## Related\n\n- [Disaster Recovery](https://docs.subscriby.net/disaster-recovery): what the program does and why.\n- [History and Undo](https://docs.subscriby.net/disaster-recovery/history-and-undo): the same ledger on the dashboard.\n- [Active Disaster Prevention](https://docs.subscriby.net/disaster-recovery/active-disaster-prevention): the features the readiness lines check.\n- [Allowances and support review](https://docs.subscriby.net/disaster-recovery/allowances-and-support-review): the quota rule and what support audits before releasing a grant.\n- [`recovery.*` webhook events](https://docs.subscriby.net/webhooks/v1/events/recovery)\n- [Ability catalog](https://docs.subscriby.net/api/v1/abilities)"
        },
        {
            "name": "Support Inbox",
            "description": "The support inbox is where a member who writes to your project bot something it does not recognise ends up: one durable **support conversation** per `(project, member, channel)`, the **saved replies** your team answers with, and the project's **support settings** that decide whether the inbox is open, how you hear about a new thread and how replies are signed. Replies sent through this API reach the member on their channel, prefixed with the project's support name so they read as coming from a person rather than the bot.\n\n## Related\n\n- [Support inbox guide](https://docs.subscriby.net/creators/support-inbox)\n- [Members](https://docs.subscriby.net/api/v1/reference/members): the people behind the threads, and where to ban or kick.\n- [Projects](https://docs.subscriby.net/api/v1/reference/projects): the project the settings live on.\n- [`support.*` webhook events](https://docs.subscriby.net/webhooks/v1/events/support): inbound traffic emits `support.conversation.opened`, `support.message.received` and, for a resolved thread, `support.conversation.reopened` from the bot pipeline; the endpoints below announce their own changes, and the `support.canned_reply.*` payloads carry a snippet's `id`, `title`, `shortcut` and `sort_order`, never its `body`.\n\n## Conversations\n\nThe conversation routes are **not** nested under a project. One call gives you the queue across every project the token can reach; pass `project_id` to narrow it. A token confined to other projects is refused with `403 FORBIDDEN`.\n\n## Saved replies\n\nA **saved reply** (a canned reply, in the route names) is a reusable snippet a creator keeps for the [support inbox](https://docs.subscriby.net/creators/support-inbox#saved-replies): an opening-hours line, a refund policy, the \"your link expired, here is how to get a new one\" answer. Each has a `shortcut` the creator types in the thread composer to pull it in, and a `sort_order` that is its position in the picker.\n\nThe saved-reply endpoints let an integration mirror that picker: read the creator's wording before answering with the [reply endpoint](https://docs.subscriby.net/api/v1/reference/support-inbox/reply-to-a-member), or keep the set in sync from a knowledge base. They run the same actions the inbox uses, so the permission checks and the order the creator arranged are the dashboard's. A token whose holder's team role lacks the support permission on the project is refused with `403 TOKEN_MISSING_ABILITY`.\n\n## Settings\n\nEvery project carries a handful of settings for its [support inbox](https://docs.subscriby.net/creators/support-inbox#settings): whether members can open a conversation at all, how the creator hears about a new one, the name replies are signed with, the acknowledgement a member gets on their first message, and whether the creator is emailed. They are columns on the project, so reading them takes only `project:view` and changing them runs the same action as the inbox's settings modal.\n\nThe settings abilities are the project abilities, not `support-conversation:*`: the settings decide how a project behaves, so the token that may read or change the project may read or change them. A token whose holder's team role may not update the project is refused with `403 TOKEN_MISSING_ABILITY`."
        },
        {
            "name": "Knowledge",
            "description": "**Knowledge** is what a project teaches [Subscriby Copilot](https://docs.subscriby.net/copilot) beyond what Subscriby already knows about it: questions with their answers, and guides, each cut into passages the Copilot is handed when a question matches. An entry marked for **members** lets the Copilot answer a member from it, in the inbox, the project bot and the chat on the portal page; an entry kept to the **team** serves the suggested reply in the inbox and, next, the panel and the platform bot. The dashboard page is **Knowledge**, the entry before Portal Designer at the end of a project's menu.\n\nThese routes take the project in the path and need the `project-knowledge:*` abilities: `view-any` for the list, `view` for one entry, `create`, `update` and `delete` for the writes. A document arrives as text over the API, where the dashboard also takes a `.txt`, `.md` or `.markdown` file; the Copilot reads the same passages either way. A PDF is not read yet on either.\n\n> **The text rides on one entry, never on the list.** `GET …/knowledge` answers every entry without its `body`; `GET …/knowledge/{entry}` and every write answer the entry with it, because a document's text can run to 50,000 characters and a project may hold 200 entries.\n\n## Related\n\n- [Knowledge in the guide](https://docs.subscriby.net/creators/knowledge): what to teach, how an entry is read, the two audiences.\n- [Copilot in Your Inbox](https://docs.subscriby.net/copilot/in-your-inbox): where the answers come out.\n- [Knowledge events](https://docs.subscriby.net/webhooks/v1/events/knowledge): `knowledge.created`, `knowledge.updated` and `knowledge.deleted`.\n- [Abilities](https://docs.subscriby.net/api/v1/abilities#project-knowledge-project-knowledge): the five abilities."
        },
        {
            "name": "Portal Design",
            "description": "**Portal Design** is the look of a project's portal page, the storefront every project has at its own address: the colours, the type, the shape of the cards and buttons, the layout, every line of wording, the blocks under the plans, the announcement bar, the media, the order and visibility of the parts, the behaviour around the plans, what search engines and shared links see, the creator's own measurement tags and stylesheet, and the language. The dashboard page is **Portal Designer**, the last entry of a project's menu, and the platform bot offers the same settings.\n\nA design lives as two documents: the **published** one members see and a **draft** being edited. Every write lands in the draft; `publish` makes it the published design and `discard` throws it away; a `preview_url` on every read shows the draft for ten minutes, and is null until the project has a handle, because there is no portal page to preview. These routes take the project in the path and need `project:view` for the read and `project:update` for the writes, the same gate as the project's own settings; a design the portal could not draw is refused as `VALIDATION_FAILED` naming the key.\n\n> **A preset recolours.** Sending `preset` alone sets the six colours from the preset; send a colour beside it to keep that one. A body text, heading or caption colour that blends into the surface or the background (under a 3:1 contrast ratio) is refused, whichever of the two you sent.\n\n## Related\n\n- [Portal Design in the guide](https://docs.subscriby.net/creators/portal-design): every section, what it changes and how the bot edits it.\n- [`project.design_published`](https://docs.subscriby.net/webhooks/v1/events/project): the event a publish raises.\n- [Abilities](https://docs.subscriby.net/api/v1/abilities#project-project): `project:view` and `project:update`."
        },
        {
            "name": "Connectors",
            "description": "A Subscriby project runs on **connectors**: the platforms it gates access on, sends messages through and takes payments from. The directory these endpoints serve is the same one the dashboard and the marketing site render, so a client reads one document and knows which connectors exist, which a creator may install today, what each can do, and exactly which fields connecting one asks for. The manifest is served whole because the creator apps render the connect form from it: no client has to know what a \"bot token\" is before the connector says so.\n\nThe catalogue is the same for every creator and never carries a credential. A project's **installations** are what the Connectors tab lists: every connector set up on the project, live and standby, with its state and health.\n\n## Related\n\n- [Resources](https://docs.subscriby.net/api/v1/reference/resources): the places a project gates on its connectors.\n- [Connector events](https://docs.subscriby.net/webhooks/v1/events/connector): `connector.*`.\n- [Ability catalogue](https://docs.subscriby.net/api/v1/abilities): `project-connector:*`.\n- [Error catalogue](https://docs.subscriby.net/api/v1/errors#connectors): every write here answers `404 RESOURCE_NOT_FOUND` with `reason: unknown_connector` for a key that names no connector, and `404 CONNECTOR_NOT_INSTALLED` for one the project does not run.\n- [MCP resources](https://docs.subscriby.net/mcp/v1/resources-reference): `subscriby://connectors/catalog` carries the whole directory for an agent to read at session start."
        },
        {
            "name": "Roles",
            "description": "A **role** is the permission set a collaborator holds on a team. Subscriby seeds three on every new team, `admin`, `manager` and `viewer`, and a team can add its own: a `support-agent` who may read and answer conversations but touch nothing else, a `finance` role that reads payouts and analytics. Each collaborator holds exactly one role, assigned when they are invited and changed through the [team members](https://docs.subscriby.net/api/v1/reference/team-members) endpoints; [groups](https://docs.subscriby.net/api/v1/reference/groups) layer extra permissions on top of it for several people at once.\n\nA role's `permissions` is a flat array of the same ability strings a personal access token carries, so a role can be matched against a token without a second round-trip, and the [ability catalog](https://docs.subscriby.net/api/v1/abilities) is the list to pick from. Changing a role changes what every holder may do from the next request; deleting one detaches its permissions and leaves its holders in the team with nothing beyond what their groups grant.\n\nRoles are read across every team the caller owns or belongs to, and a role on any other team is a `404 RESOURCE_NOT_FOUND`, never a `403`, so existence never leaks. Every write announces itself as a `role.*` event.\n\n## Related\n\n- [Teams](https://docs.subscriby.net/api/v1/reference/teams)\n- [Team Members](https://docs.subscriby.net/api/v1/reference/team-members)\n- [Groups](https://docs.subscriby.net/api/v1/reference/groups): named permission bundles several people share\n- [Ability catalog](https://docs.subscriby.net/api/v1/abilities)\n- [`role.*` webhook events](https://docs.subscriby.net/webhooks/v1/events/role)"
        },
        {
            "name": "Subscriptions",
            "description": "A **subscription** is one member's purchase of one plan: the row that says who bought what, on which payment method, for how much, and until when. Every checkout on the portal or in the bot, every redeemed access code and every cardless trial creates one, so there is no `POST` here: a subscription comes into being when a member pays or redeems, and these endpoints let you read it, follow the access it granted and drive the rest of its life.\n\nThe row carries a `payment_status` that tracks the provider's view of the money (`trialing`, `active`, `past_due`, `paused`, `canceled`, `expired` and the rest), an `ends_at` that already includes any outage compensation the member was owed, and, when read individually, its **grants**: the access ledger with one row per resource the plan unlocks, and per dated window for a pass. A grant says which connector admitted the member, how (`bearer_link`, `membership`, `role` or `creator_task`), where it stands (`pending_identity`, `pending`, `held`, `granted`, `revoked` or `failed`) and why when it failed. Read the grants, not the payment status, to know whether a member is actually inside the channel.\n\nThe lifecycle endpoints are RPC-style actions rather than field edits, because each one talks to a payment provider or a connector on the way: **cancel** queues the provider-side cancellation and answers `202`; **pause** and **unpause** suspend and restore access while billing continues; **reactivate** calls off a scheduled cancellation, on Stripe only, since the other providers end the agreement outright; **reissue** revokes the member's invite links and mints fresh ones; and **remind** re-sends a pass holder the links they have not used yet. Every transition announces itself as a `subscription.*` event. Subscriptions are read across every project the token reaches, a `scope:project` token sees only its projects, and a subscription of any other project is a `404` on every endpoint here.\n\n## Related\n\n- [Members](https://docs.subscriby.net/api/v1/reference/members)\n- [Plans](https://docs.subscriby.net/api/v1/reference/plans)\n- [Pass Windows](https://docs.subscriby.net/api/v1/reference/pass-windows): nudge every holder of one window at once.\n- [Webhook Events](https://docs.subscriby.net/api/v1/reference/webhook-events)\n- [`subscription.*` events](https://docs.subscriby.net/webhooks/v1/events/subscription): every transition these endpoints and the payment providers announce."
        },
        {
            "name": "Teams",
            "description": "Teams group creators, roles, and projects. Tokens always resolve a single team via the mandatory `scope:team:<uuid>` tuple in their abilities array, and these endpoints let you introspect and manage the teams your account can act on.\n\n> **Creating a team is a Growth capability; deleting one is not.** Create and update require a platform tier that includes Teams; on a lower tier they return `403 TEAM_TIER_REQUIRED` and change nothing, the same gate the dashboard applies at **Settings → Teams**. Delete is not gated. See what the tier gates below.\n\n## What the tier gates\n\nTeams, roles and groups sell on the Growth tier, so one rule runs through every write in this part of the API:\n\n> **Granting access is a paid capability. Withdrawing it is not.**\n\n|                                                                                            | Gated on Growth                |\n| ------------------------------------------------------------------------------------------ | ------------------------------ |\n| Create a team, role or group                                                               | Yes                            |\n| Rename or re-permission one                                                                | Yes                            |\n| Invite a collaborator, or change their role                                                | Yes                            |\n| Delete a team, role or group                                                               | No                             |\n| Remove a collaborator, or withdraw an invitation                                           | No                             |\n| [Replace a group's members](https://docs.subscriby.net/api/v1/reference/groups/replace-a-groups-members) | Only if the sync adds somebody |\n\nThe asymmetry is deliberate. A creator who drops below Growth still has collaborators attached, and gating removal would leave them unable to revoke access they no longer want to be paying for; a downgrade would become a permanent grant. So the tier decides what you can build, never what you can take apart.\n\nThe same rule holds on the [MCP tools](https://docs.subscriby.net/mcp/v1/tools-reference) and in the dashboard.\n\n## Related\n\n- [Team Members](https://docs.subscriby.net/api/v1/reference/team-members): invite, re-role and remove collaborators\n- [Roles](https://docs.subscriby.net/api/v1/reference/roles): the permission sets a member can hold\n- [Groups](https://docs.subscriby.net/api/v1/reference/groups): named permission bundles several people share\n- [`team.*` webhook events](https://docs.subscriby.net/webhooks/v1/events/team)"
        },
        {
            "name": "Team Members",
            "description": "**Team members** are the humans who collaborate inside a team: the creator who owns it and the people they invited to help run its projects. They are distinct from a project's *members*, the subscribers who buy plans, who are modelled separately and reached through the [Members](https://docs.subscriby.net/api/v1/reference/members) endpoints.\n\nA collaborator joins by invitation to an email address with a role code, holds one [role](https://docs.subscriby.net/api/v1/reference/roles) at a time, and leaves either by removal or by having an unaccepted invitation withdrawn; both take the same ability, because both revoke the same prospective access. The team's owner appears as the first row of the roster but is not a membership: ownership cannot be re-roled or removed here. Reading who is on a team and reading how to reach them are separate asks, so `email` is present only when the token carries `team-member:view` and is otherwise absent from the row altogether.\n\nThe list is not paginated, since a team's collaborator list is small by construction. Every change announces itself as a `team.*` event.\n\n## What the API refuses\n\nThe teams package enforces these itself; the API restates them rather than letting a plainly-invalid request surface as a `500`.\n\n| Attempt                                   | Result                                          |\n| ----------------------------------------- | ----------------------------------------------- |\n| Re-role or remove the **owner**           | `404`: ownership is not a membership row        |\n| Invite someone already in the team        | `422`                                           |\n| Name a `role` code the team does not have | `422`                                           |\n| Address a user who is not in the team     | `404`                                           |\n| Address a team the caller cannot see      | `404`                                           |\n\nA team is visible only when the caller owns it or is a member. Tokens scoped to a different team get `404 RESOURCE_NOT_FOUND` on every route here; existence never leaks.\n\n## Related\n\n- [Roles](https://docs.subscriby.net/api/v1/reference/roles)\n- [Teams](https://docs.subscriby.net/api/v1/reference/teams)\n- [Ability catalog](https://docs.subscriby.net/api/v1/abilities)\n- [`team.*` webhook events](https://docs.subscriby.net/webhooks/v1/events/team)"
        },
        {
            "name": "Tokens",
            "description": "Personal access tokens are what authorize every REST and MCP call. They look like `sbt_live_<id>_<secret>` in production and `sbt_test_<id>_<secret>` everywhere else, and the plaintext value exists exactly once: in the response that created it.\n\nYou can mint one in the dashboard under **Settings → API Tokens**, or through the mint endpoint below. No `token.*` webhook events exist: mint and revoke are deliberately silent, because deliveries would let an observer fingerprint credential churn on an account they cannot otherwise see.\n\n## Authorization\n\nOwnership is necessary but not sufficient.\n\n> **Changed in 3.0.0.** These routes previously required **no ability at all**, on the reasoning that owning a token is the permission. It is not: a token scoped to nothing but `dashboard:read` could enumerate and revoke every other token its owner held, including the ones running their automation. Each route now demands its matching `token:*` ability as well. If you have a token that reads analytics and also manages tokens, add `token:view-any` / `token:delete` to it, or better, mint a separate one.\n\nTokens belonging to another user are invisible: every route returns `404 RESOURCE_NOT_FOUND` for an id outside the caller's own set, so the API cannot be used to probe which ids exist.\n\n## Related\n\n- [Authentication](https://docs.subscriby.net/api/v1/authentication): the `scope:team:` tuple and the bearer header.\n- [Ability catalog](https://docs.subscriby.net/api/v1/abilities): every ability string a token can carry.\n- [Tenancy and scopes](https://docs.subscriby.net/api/v1/tenancy-and-scopes): how team and project scoping combine."
        },
        {
            "name": "Me",
            "description": "`GET /v1/me` is the first call a client makes. It answers \"who am I acting as?\" in one round trip: the creator behind the token, the **team the token is scoped to** (the id every project call takes), every team they belong to, the platform plan and the capabilities it grants, the accounts linked on the connectors and where alerts go. The dashboard shows the same facts across **Settings → Profile**, **Security** and **Notifications**; a mobile or desktop client renders its home screen from this payload.\n\nIt lives under `/v1/me` with no project or team in the path because it is about the caller, never a project.\n\n## Related\n\n- [Teams](https://docs.subscriby.net/api/v1/reference/teams): `GET /v1/teams/current` returns `current_team` alone.\n- [Identities](https://docs.subscriby.net/api/v1/reference/identities): the accounts behind `identities`.\n- [Alert Destinations](https://docs.subscriby.net/api/v1/reference/alert-destinations): change where alerts go.\n- [`get_me`](https://docs.subscriby.net/mcp/v1/tools/account/get-me): the same payload as an MCP tool."
        },
        {
            "name": "Identities",
            "description": "A **linked identity** is an account you hold on a connector, tied to your Subscriby creator account. It is what lets the platform bot reach you, lets you manage projects from it, and lets the connector's sign-in button sign you in. The dashboard shows the same list under **Settings → Security → Linked accounts**.\n\nThese routes are about the **caller's own** account, so they live under `/v1/me` and need no project or team in the path. A member's connected accounts are a different thing, read under [Members](https://docs.subscriby.net/api/v1/reference/members).\n\n## Related\n\n- [Signing in with a connected account](https://docs.subscriby.net/account/social-login): linking and unlinking from the dashboard.\n- [Me](https://docs.subscriby.net/api/v1/reference/me): the same list embedded as `identities`.\n- [Tokens](https://docs.subscriby.net/api/v1/reference/tokens): minting a token with the `account:*` abilities."
        },
        {
            "name": "Alert Destinations",
            "description": "An **alert destination** is a place your creator alerts go: one of the accounts linked to your creator account on a connector, or your email address. Each destination carries the **classes** of alert it receives (`sales`, `support`, `recovery`, `billing`, `security`, `passes`, `onboarding`), or every class when `classes` is `null`. The dashboard shows the same grid under **Settings → Notifications → Alert destinations**.\n\nThese routes are about the **caller's own** account, so they live under `/v1/me` and need no project or team in the path.\n\n## Related\n\n- [Identities](https://docs.subscriby.net/api/v1/reference/identities): the accounts a destination can point at.\n- [Me](https://docs.subscriby.net/api/v1/reference/me): the destinations alongside your teams, plan capabilities and connected accounts in one call.\n- [Email and notifications](https://docs.subscriby.net/account/notifications): the settings screen and what each class covers."
        },
        {
            "name": "Notifications",
            "description": "Every alert Subscriby sends a creator (a sale, a support backlog, a bot or channel that went silent, a billing or security notice, a pass window, an onboarding nudge) also lands in the **Notifications Center**: the sidebar entry with its unread count and popover, and the page at `/notifications`. These endpoints read the same rows and make the same two marks, so a client, a Zap or an agent can show the inbox and clear it.\n\nThe rows belong to the **creator behind the token**, never to a team or a project, so everything lives under `/v1/me`. `account:read` lists them; `account:write` marks them.\n\n## Related\n\n- [Me](https://docs.subscriby.net/api/v1/reference/me): the caller, with `unread_notifications`, so a client can draw the sidebar badge without listing the inbox.\n- [Alert Destinations](https://docs.subscriby.net/api/v1/reference/alert-destinations): where each class of alert is delivered.\n- [Notifications guide](https://docs.subscriby.net/account/notifications): the Notifications Center on the dashboard."
        },
        {
            "name": "Partner Program",
            "description": "The **Partner Program** is Subscriby's own: a creator who brings other creators to Subscriby earns a share of every platform invoice those creators pay, for twelve months from each one's first paid Starter or Growth invoice, settled as Subscriby Credit on their own invoices or paid out in cash. The dashboard shows the same standing under **Partner Program** in the sidebar, and the bot's 🤝 Partner Program button shows it in chat.\n\nThese routes are about the **caller's own** partnership, so they live under `/v1/me` and need no project or team in the path; the reads need `account:read`, the two writes `account:write`. Applying is done in person, on the dashboard or in the bot, so a creator who never applied is `404 RESOURCE_NOT_FOUND` on every route here, and an application still under review reads back with `status: \"applied\"` and nothing computed.\n\n> **The destination a rail pays to never travels.** The partner object names the rail (`payout_method`) and says whether it is complete (`payout_details_complete`); the PayPal address, the wallet or the bank account are written encrypted by `PUT /v1/me/partner/payout-details` and returned by nothing.\n\n## Related\n\n- [Partner Program in the account guide](https://docs.subscriby.net/account/partner-program): the walkthrough, from the application to the payout.\n- [`partner.*` webhooks](https://docs.subscriby.net/webhooks/v1/events/partner): the ten events; a sign-up, a conversion, a commission moving and a payout fire from the ledger, never from a call here.\n- [Me](https://docs.subscriby.net/api/v1/reference/me): `partner_code` and `partner_link` ride on `GET /v1/me` once approved.\n- [Partner Program Terms](https://www.subscriby.net/legal/partners): what the terms endpoint accepts.\n- [Abilities](https://docs.subscriby.net/api/v1/abilities#account): `account:read` and `account:write`."
        },
        {
            "name": "Transaction Fees",
            "description": "**Transaction Fees** are what Subscriby charges a creator on the money their members pay: a percentage of each payment at the plan's rate, a code redeemed past the plan's free allotment, the metered fees a platform trial waived, emails sent to members during a recovery, and the cost of collecting an invoice's fee lines. Every one of them is a line of the creator's **Transaction Fees ledger**, written the moment the fee is decided and never re-priced. The dashboard shows the same ledger under **Plans & Billing → Transaction Fees**, with a month picker and a CSV export.\n\nThese routes are about the **caller's own** fees, so they live under `/v1/me` and need no project or team in the path; both need `account:read`. Nothing here writes: a line is written by the sale, the meter event or the invoice that decided the fee.\n\n> **Two channels, one ledger.** A fee is collected one of two ways and the ledger says which on every line. `connect_at_source`: Stripe Connect deducted it from the member's payment as it passed through, so it never appears on a Subscriby invoice. `metered`: it was reported to the usage meter and billed on the creator's own Subscriby invoice; once that invoice is paid, the line carries its `invoice_id` and `invoiced_at`, so every unit of a Transaction Fees invoice line can be followed back to the sale it was earned on.\n\n## Related\n\n- [Transaction Fees in the guide](https://docs.subscriby.net/fees): the rates, the two billing routes, trials and refunds.\n- [Me](https://docs.subscriby.net/api/v1/reference/me): the account the fees belong to.\n- [Abilities](https://docs.subscriby.net/api/v1/abilities#account): `account:read`."
        },
        {
            "name": "Copilot Credits",
            "description": "**Copilot Credits** are the prepaid pool that pays for [Subscriby Copilot](https://docs.subscriby.net/copilot) once the month's free allowance is used: paid credit from packs of $10, $25, $50 and $100, and free credit, the bonus the three larger packs add, a promotion or goodwill, spent before the paid part. Every plan includes free operator turns and member answers each month; past them a turn, an inbox suggestion or a member answer draws its price from the pool. The pool is the creator's own, never a project's, and never touches the Stripe customer balance or a plan invoice.\n\nThese routes are about the **caller's own** credits, so they live under `/v1/me` and need no project or team in the path. The two reads need `account:read`, the two writes `account:write`. Every amount is an integer in US cents.\n\n> **Buying is a redirect, not a charge.** `POST /v1/me/copilot-credits/packs` opens a Stripe Checkout session and answers its URL. Nothing is charged and no credit lands until the creator pays on that page; the session reports back through Stripe's webhook, and `copilot_credit.purchased` fires when the credit is granted. A pack cannot be bought from a server alone.\n\n## Related\n\n- [Credits & Credit Packs](https://docs.subscriby.net/credits): packs, bonuses, the auto top-up, the cap, refunds and the statement.\n- [Turns & Credits](https://docs.subscriby.net/copilot/turns-and-credits): what a turn is and how it is paid.\n- [Copilot Credits events](https://docs.subscriby.net/webhooks/v1/events/copilot-credit): `copilot_credit.purchased`, `.granted`, `.low` and `.refunded`.\n- [Abilities](https://docs.subscriby.net/api/v1/abilities#account): `account:read` and `account:write`."
        },
        {
            "name": "Webhook Endpoints",
            "description": "A **webhook endpoint** is a URL of yours that Subscriby posts events to, with the event families it subscribes to and a signing secret you verify each delivery against. An endpoint belongs to the team and may be narrowed to one project; the secret is shown exactly twice, in the answer to registering the endpoint and in the answer to rotating it, and never appears on a read.\n\nEach endpoint carries its delivery health: the last success and failure, and `disabled_at` when Subscriby switched it off after too many consecutive failures or when someone paused it. **Pause** and **resume** are the dashboard's on/off switch, and events raised while paused are not queued or replayed; **test** enqueues a synthetic delivery so a new handler can be checked before real traffic; **rotate secret** revokes the old secret at once, so deploy the new one first. The delivery log and the replay of a dead-lettered row live under [webhook deliveries](https://docs.subscriby.net/api/v1/reference/webhook-deliveries).\n\nEvery member of the team may list and read endpoints, but only the member who registered one, or the team owner, may rotate, test, pause, resume or delete it. The same routes answer under the `/v1/webhook-subscriptions` alias so Zapier's subscribe and unsubscribe hooks can target them directly. Endpoint lifecycle emits no webhooks of its own, since that would be recursive.\n\n## The webhook-subscriptions alias\n\n`GET`, `POST /v1/webhook-subscriptions` and `DELETE /v1/webhook-subscriptions/{endpoint}` are 1:1 aliases of the list, create and delete endpoints below, so Zapier's subscribe and unsubscribe hooks can target them directly. They take the same abilities, bodies and answers and are not listed separately. The retired umbrella ability `webhook-endpoint:manage` still satisfies every route here on tokens that carry it; new tokens take the per-verb abilities.\n\n## Who may change an endpoint\n\nEvery member of the team can list and read the team's endpoints, but only the member who registered an endpoint, or the team owner, may rotate its secret, test it, pause or resume it, or delete it. A token minted by another member receives `403 FORBIDDEN` on those calls; an endpoint outside the token's team is a `404 RESOURCE_NOT_FOUND`, never a `403`, so an id cannot be probed.\n\n## Related\n\n- [Webhook Deliveries](https://docs.subscriby.net/api/v1/reference/webhook-deliveries): the delivery log, and how to replay a failed or dead-lettered row.\n- [Webhook Events](https://docs.subscriby.net/api/v1/reference/webhook-events): consume recent deliveries over REST. Endpoint lifecycle itself emits no outbound webhooks, since that would be recursive; every other family can be subscribed to.\n- [Security model](https://docs.subscriby.net/webhooks/v1/security): signatures, public hosts and the IP allowlist.\n- [Ability catalog](https://docs.subscriby.net/api/v1/abilities)"
        },
        {
            "name": "Webhook Deliveries",
            "description": "Every event Subscriby posts to one of your [webhook endpoints](https://docs.subscriby.net/api/v1/reference/webhook-endpoints) is a **delivery**: one row per endpoint per event, carrying the signed envelope that was sent, the target's response and where the row is on the [retry ladder](https://docs.subscriby.net/webhooks/v1/retries-and-delivery). This is the same log the dashboard shows under **Settings → Webhook Deliveries**, over REST, so an integrator on call can see why a consumer rejected an event without signing in.\n\nThe two replay paths are the dashboard's too. A single failed or dead-lettered row can be retried from the start of the ladder, and everything the team dead-lettered since an instant can be replayed at once after a fix. A token that still carries the retired `webhook-endpoint:manage` satisfies both abilities on this page; see the [ability catalog](https://docs.subscriby.net/api/v1/abilities).\n\n## Related\n\n- [Webhook Endpoints](https://docs.subscriby.net/api/v1/reference/webhook-endpoints): the targets these deliveries were posted to; pause one while you fix it.\n- [Webhook Events](https://docs.subscriby.net/api/v1/reference/webhook-events): the polling view of recent deliveries by event type.\n- [Retries and delivery](https://docs.subscriby.net/webhooks/v1/retries-and-delivery): the ladder, dead-lettering and auto-disable.\n- [Testing and debugging](https://docs.subscriby.net/webhooks/v1/testing-and-debugging)"
        },
        {
            "name": "Webhook Events",
            "description": "A read-only polling endpoint that surfaces the most recent webhook deliveries for a given event type. The envelope is identical to the live webhook POST body, so polling samples and live hook payloads are indistinguishable.\n\n> **Why it exists.** REST Hook integrations (Zapier, Make, n8n) can satisfy the polling fallback contract even when the user has not yet fired a live event. If your team has no deliveries for the requested type, the response is an empty `data` array; consumers fall back to their static sample in that case.\n\nThe endpoint takes `webhook-delivery:view-any`. A token that still carries the retired `webhook-endpoint:manage` satisfies it.\n\n## Related\n\n- [Webhook Endpoints](https://docs.subscriby.net/api/v1/reference/webhook-endpoints): create and manage the endpoints whose deliveries feed this list.\n- [Webhook Deliveries](https://docs.subscriby.net/api/v1/reference/webhook-deliveries): the same rows with their delivery outcome.\n- [Event Reference](https://docs.subscriby.net/webhooks/v1/events): every event and its payload.\n- [Ability catalog](https://docs.subscriby.net/api/v1/abilities)"
        },
        {
            "name": "project.* events",
            "description": "Project lifecycle, resource link / unlink, payment method changes. Fires whenever a project is created, updated, archived, restored, or deleted, plus transitions on its resources and payment methods. A project's connectors have their own family, [`connector.*`](https://docs.subscriby.net/webhooks/v1/events/connector).\n\n| Event                            | Fires when                                                                                                                                                                       |\n| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `project.created`                | A creator registers a new project.                                                                                                                                               |\n| `project.updated`                | Any mutable project field changes (name, description, handle, terms, privacy).                                                                                                   |\n| `project.archived`               | The project's `active` flag is set to false. Existing subscriber access is not revoked.                                                                                          |\n| `project.restored`               | An archived project is re-activated.                                                                                                                                             |\n| `project.deleted`                | A project is hard-deleted. Fires once, then nothing else from that project.                                                                                                      |\n| `project.design_published`       | A drafted portal design was published, from the designer, the platform bot, the API or `publish_portal_design`; names the sections that changed.                                 |\n| `project.resource.created`       | A manual resource is registered under the project via the REST API or MCP. A place a connector gates (a channel, group or supergroup) arrives as `project.resource.linked` instead. |\n| `project.resource.linked`        | An existing place on a connector is linked as a resource.                                                                                                                        |\n| `project.resource.unlinked`      | A resource is disconnected from the project.                                                                                                                                     |\n| `project.resource.deleted`       | A resource row is soft-deleted (`deleted_at` is stamped; the row is retained).                                                                                                   |\n| `project.resource.updated`       | A resource's title, description or on/off switch changes, with a `changes` map of what moved.                                                                                    |\n| `project.resource.status_changed` | A channel or group enters or exits a degraded state: banned, deleted, or the bot lost its rights.                                                                               |\n| `project.payment_method.updated` | A payment gateway's switch, link state or credential keys change. Names the changed keys, never a value.                                                                         |\n| `project.payment_method.deleted` | A payment gateway is removed from the project.                                                                                                                                   |\n\n## Example payload\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"project.created\",\n  \"created_at\": \"2026-05-18T10:05:00Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n  \"data\": {\n    \"project\": {\n      \"id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n      \"name\": \"Research Premium\",\n      \"handle\": \"research-premium\",\n      \"active\": true,\n      \"team_id\": \"a83f0d51-4c92-4b7e-8615-2fd9e70a3c86\"\n    }\n  }\n}\n```\n\n## Required abilities\n\nThis family is the one exception to \"one ability per family\": the resource and payment-method events are scoped separately from the project itself.\n\n| Events                                                                                                                                                                       | Ability                       |\n| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |\n| `project.created`, `project.updated`, `project.archived`, `project.restored`, `project.deleted`, `project.design_published`                                                  | `project:view`                |\n| `project.resource.created`, `project.resource.linked`, `project.resource.unlinked`, `project.resource.updated`, `project.resource.deleted`, `project.resource.status_changed` | `project-resource:view`       |\n| `project.payment_method.updated`, `project.payment_method.deleted`                                                                                                           | `project-payment-method:view` |",
            "x-webhook-family": "project"
        },
        {
            "name": "plan.* events",
            "description": "Fires on every change to a plan's state, pricing or storefront position. Consumers commonly use these to keep a pricing-page cache or a CRM field in sync.\n\n| Event                 | Fires when                                                                                         |\n| --------------------- | -------------------------------------------------------------------------------------------------- |\n| `plan.created`        | A plan is first created on a project.                                                              |\n| `plan.updated`        | Any mutable plan field changes (price, interval, trial, eligibility filters).                      |\n| `plan.activated`      | An inactive plan is flipped to active.                                                             |\n| `plan.deactivated`    | An active plan is flipped to inactive (still viewable, not purchasable).                           |\n| `plan.sold_out`       | A plan hit its sales cap, or a pass series filled its last seat, and paused itself.                |\n| `plan.order_changed`  | The creator arranged the order plans appear in on the portal and in the bot, or reset it.          |\n| `plan.deleted`        | The plan is soft-deleted (row retained with `deleted_at` set; reads return 404).                   |\n| `plan.sync_completed` | A plan is synced to the external payment-provider catalog (Stripe, PayPal, CoinPayments, Razorpay). |\n\n## Example envelope\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"plan.updated\",\n  \"created_at\": \"2026-05-18T10:05:00Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n  \"data\": {\n    \"plan\": {\n      \"id\": \"c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b\",\n      \"name\": \"Premium Monthly\",\n      \"price\": \"29.0000\",\n      \"currency_id\": \"8f27a0d4-63be-4915-8c07-1a5d9e34b628\",\n      \"billing_cycle\": \"month\",\n      \"active\": true\n    },\n    \"changes\": {\n      \"price\": { \"from\": \"25.0000\", \"to\": \"29.00\" }\n    }\n  }\n}\n```\n\nThe `data.changes` block is present on `plan.updated` and identifies the fields that changed. For other events it is omitted. Each `from` is the plan's previous value after model casting, so `price` is a string and an enum column is its backed string value, while each `to` is the caller-supplied value exactly as validated.\n\n## Required ability\n\nTokens subscribing to `plan.*` events must carry `project-subscription-plan:view` at mint time.",
            "x-webhook-family": "plan"
        },
        {
            "name": "pass.* events",
            "description": "Time-limited pass access window lifecycle: opened, closed, cancelled, and what happened to each holder. Fires as a time-limited pass plan's scheduled access windows open, close and, when a creator postpones one, get cancelled. A pass sells access to one dated window rather than an ongoing membership, so most of these describe the window itself: use them to drive slate-level automation such as posting a line-up when access opens or a recap when it ends.\n\nThe `holder_*` events are the exception: each describes one buyer rather than the window. Cancelling a window resettles every buyer individually and the outcomes need different handling downstream (a move is a date change to push into a calendar or CRM, a stranding is money owed) so each holder gets its own event. `holder_queued` and `holder_missed` are the same idea applied to attendance: who is set up to be let in, and who never turned up.\n\nIf the plan is a [Pass Series](https://docs.subscriby.net/creators/pass-series), the window-level events and `holder_queued`/`holder_missed` still fire for every underlying window, with the [`pass_series.*` family](https://docs.subscriby.net/webhooks/v1/events/pass-series) firing alongside them to describe the slate. `holder_moved` and `holder_stranded` are the exception: a season-ticket holder gets `pass_series.leg_substituted` or `pass_series.leg_dropped` *instead of*, not alongside, those two.\n\nFor ordinary per-subscriber grants and revocations, use `member.resource_added` and `member.resource_removed` instead.\n\n| Event                   | Fires when                                                          |\n| ----------------------- | ------------------------------------------------------------------- |\n| `pass.window_scheduled` | A new access window came into existence.                            |\n| `pass.window_opened`    | An access window started and holders were admitted.                 |\n| `pass.window_closed`    | An access window ended and holders were removed.                    |\n| `pass.window_cancelled` | A creator cancelled a window and its holders were resettled.        |\n| `pass.holder_queued`    | A holder tapped their invite link and is now queued.                |\n| `pass.holder_moved`     | One holder was moved to the next available window.                  |\n| `pass.holder_missed`    | A window closed and one holder never turned up.                     |\n| `pass.holder_stranded`  | One holder's pass ended with no replacement; a refund is owed.      |\n\n## What a cancellation emits\n\nCancelling one window produces several events in a single burst:\n\n| Event                         | Fires                                              |\n| ----------------------------- | -------------------------------------------------- |\n| `pass.holder_moved`           | Once per holder who was moved (ordinary pass)      |\n| `pass_series.leg_substituted` | Once per holder who was moved (season ticket)      |\n| `pass.holder_stranded`        | Once per holder whose pass ended (ordinary pass)   |\n| `pass_series.leg_dropped`     | Once per holder who lost that date (season ticket) |\n| `pass.window_cancelled`       | Once, last, carrying the three tallies and the choice |\n\nWhich of each pair fires depends on what the holder bought: a single-window pass ends, whereas a season ticket loses one date and carries on.\n\nA cancelled window never subsequently emits `pass.window_opened` or `pass.window_closed`; it is removed from the lifecycle entirely.\n\n## Timestamps are UTC\n\nEvery payload carries its window times in UTC. A pass schedule is authored in the creator's timezone, so convert before displaying: a window advertised as 9:00 AM in New York is `13:00+00:00` or `14:00+00:00` depending on daylight saving.\n\n## Example envelope\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"pass.window_opened\",\n  \"created_at\": \"2026-09-20T13:00:04Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n  \"data\": {\n    \"plan_id\": \"c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b\",\n    \"window_id\": \"3d5a8c72-b016-4e94-8fa7-61c209d4e738\",\n    \"starts_at\": \"2026-09-20T13:00:00+00:00\",\n    \"ends_at\": \"2026-09-21T03:00:00+00:00\",\n    \"subscribers_affected\": 47\n  }\n}\n```\n\n## Required abilities\n\nTokens subscribing to a window-level event (`window_scheduled`, `window_opened`, `window_closed`, `window_cancelled`) must carry `project-subscription-plan:view`: a pass window belongs to the plan that sells it, so it is scoped with the plan rather than with the subscription that holds it.\n\nThe holder-level events (`holder_queued`, `holder_moved`, `holder_missed`, `holder_stranded`) describe a specific purchase and therefore require `project-subscription:view` instead.",
            "x-webhook-family": "pass"
        },
        {
            "name": "pass_series.* events",
            "description": "Season-ticket lifecycle: bought, each date completing, dates added or dropped mid-season, and the holders-only presale on the next one. Fires across the life of a [Pass Series](https://docs.subscriby.net/creators/pass-series), a season ticket sold once that grants a whole slate of *other* pass plans' dated windows.\n\nThe family exists because a series is not just a pass with more dates. A season **grows** when rules absorb new windows, **changes** when a date is cancelled, and **progresses** as each date runs, and none of that has an equivalent on a single-window pass. The `pass.*` family still fires for every underlying window, because each date is a real window on a real plan; these describe the slate.\n\n> **Two payload facts integrators get wrong.** **`refund_per_holder` on `pass_series.leg_dropped` is a figure, not an action.** Subscriby never moves the money; the creator does. An automation that treats it as \"already refunded\" will double-refund. **`pass_series.purchased` fires in addition to `subscription.activated`**, because a series *is* a subscription row. An endpoint subscribed to both gets two deliveries for one purchase and must de-duplicate on `subscription_id`.\n\n| Event                         | Fires when                                                        |\n| ----------------------------- | ----------------------------------------------------------------- |\n| `pass_series.purchased`       | A season ticket was bought and its whole slate issued.            |\n| `pass_series.leg_completed`   | One date of a holder's season finished, with running attendance.  |\n| `pass_series.completed`       | A holder reached the last date, with final tallies.               |\n| `pass_series.leg_added`       | A rule absorbed a new window into a live season.                  |\n| `pass_series.leg_substituted` | A cancelled date was replaced and a holder moved.                 |\n| `pass_series.leg_dropped`     | A cancelled date left a season, with the pro-rata figure.         |\n| `pass_series.seats_exhausted` | A capped season sold its last seat.                               |\n| `pass_series.presale_opened`  | Holders were given first refusal on the next season.              |\n\n## Which scope each event is about\n\n| Scope                                   | Events                                                                      | Ability                          |\n| --------------------------------------- | --------------------------------------------------------------------------- | -------------------------------- |\n| **The slate**: the plan and its dates   | `leg_added`, `seats_exhausted`, `presale_opened`                            | `project-subscription-plan:view` |\n| **One holder**: a purchase and a person | `purchased`, `leg_completed`, `leg_substituted`, `leg_dropped`, `completed` | `project-subscription:view`      |\n\nThe split mirrors the `pass.*` family, where `window_*` events describe the window and `holder_*` events describe a person. Subscribe to the scope you actually act on.\n\n## Building a season timetable elsewhere\n\nThe four events that keep an external calendar honest, in the order you need them:\n\n1. `pass_series.purchased`: create the entries. Read the plan's `pass_series.windows` for the full slate.\n2. `pass_series.leg_added`: add an entry. Seasons composed with rules grow after they sell.\n3. `pass_series.leg_substituted`: move an entry, using `from_window_id` and `to_window_id`.\n4. `pass_series.leg_dropped`: remove an entry.\n\nSubscribers get this for free: the portal offers a calendar feed that stays in step on its own. The events are for putting the same schedule somewhere Subscriby cannot reach.\n\n## Example envelope\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"pass_series.purchased\",\n  \"created_at\": \"2026-09-01T11:03:44Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n  \"data\": {\n    \"subscription_id\": \"5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4\",\n    \"subscriber_id\": \"2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80\",\n    \"plan_id\": \"c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b\",\n    \"plan_name\": \"Autumn Season Ticket\",\n    \"passes_total\": 10,\n    \"passes_granted\": 9,\n    \"passes_already_held\": 1,\n    \"starts_at\": \"2026-09-20T13:00:00Z\",\n    \"ends_at\": \"2026-11-29T22:00:00Z\",\n    \"seat_cap\": 50,\n    \"seats_remaining\": 13\n  }\n}\n```\n\n## Related\n\n- [`pass.*` events](https://docs.subscriby.net/webhooks/v1/events/pass): the underlying windows opening, closing and being cancelled. Every series date is one of these too.\n- `plan.deactivated`: a finished season taking itself off sale, with `reason: series_exhausted`.\n- [Pass Series guide](https://docs.subscriby.net/creators/pass-series): the feature itself, control by control.",
            "x-webhook-family": "pass_series"
        },
        {
            "name": "coupon.* events",
            "description": "Coupon code lifecycle and redemption. Fires as coupon codes are authored, switched on and off, deleted, and redeemed at checkout. A coupon is one code many subscribers can redeem for money off: the multi-redemption counterpart to an [access code](https://docs.subscriby.net/webhooks/v1/events/access-code), which is one code for one person and grants access outright.\n\nFive of these describe the code itself and are driven by the creator. Two describe money: `coupon.redeemed` fires once per settled checkout, and `coupon.exhausted` fires the moment the last remaining use is taken.\n\n| Event                | Fires when                                                |\n| -------------------- | --------------------------------------------------------- |\n| `coupon.created`     | A new coupon code was authored.                           |\n| `coupon.updated`     | A coupon's terms changed, with a list of what moved.      |\n| `coupon.activated`   | A coupon was switched on and is being offered again.      |\n| `coupon.deactivated` | A coupon was switched off and stops being offered.        |\n| `coupon.deleted`     | A coupon was removed, carrying its final snapshot.        |\n| `coupon.redeemed`    | A subscriber's discounted payment settled.                |\n| `coupon.exhausted`   | The last remaining use was taken.                         |\n\n## The lifecycle events nest a `coupon` snapshot\n\n`created`, `updated`, `activated`, `deactivated` and `deleted` all carry the same nested object under `data.coupon`, so one consumer can handle all five:\n\n```json\n{\n  \"coupon\": {\n    \"id\": \"4b9d3e08-a1f6-4275-9c83-7e01d6a2f594\",\n    \"code\": \"BLACKFRIDAY\",\n    \"name\": \"Black Friday 2026\",\n    \"discount_type\": \"percentage\",\n    \"discount_value\": \"25.0000\",\n    \"currency_id\": null,\n    \"duration\": \"once\",\n    \"max_redemptions\": 500,\n    \"max_redemptions_per_user\": 1,\n    \"minimum_amount\": null,\n    \"starts_at\": \"2026-11-27T00:00:00+00:00\",\n    \"expires_at\": \"2026-12-01T00:00:00+00:00\",\n    \"active\": true\n  }\n}\n```\n\n> **The snapshot deliberately omits redemption counts.** Counts move independently of the coupon row, so a lifecycle event quoting one would be reporting a figure that was already stale by the time the webhook landed. Use `coupon.redeemed` for counts, or read the current figure from [the coupon endpoint](https://docs.subscriby.net/api/v1/reference/coupons).\n\n`coupon.redeemed` and `coupon.exhausted` do **not** use this shape; they are flat, because they describe a transaction rather than the code.\n\n## `discount_value` is a decimal string\n\nIt is sent as a string, not a number. On `coupon.updated`, `coupon.activated`, `coupon.deactivated` and `coupon.deleted` it is read back from the database and carries four decimal places (`\"25.0000\"`); on `coupon.created` it is the value exactly as submitted (`\"25\"`), because that payload is built before any round trip. `minimum_amount` follows the same rule. Parse it as a decimal either way, never a float; money arithmetic on a float is how a $9.99 charge becomes $9.98.\n\n`currency_id` is `null` on a percentage coupon and set on a fixed-amount one, because a percentage applies to a plan in any currency and a fixed amount only to plans priced in its own.\n\n## An empty plan restriction means every plan\n\nThe lifecycle payloads do not carry the plan restriction list. If you need it, read the coupon from the API, and read `plan_ids: []` as *applies to every plan in the project*, including plans added later. It does not mean *applies to nothing*.\n\n## Required ability\n\nEvery event in this family requires `project-coupon:view` at token mint time.\n\n## Related\n\n- [`access_code.*`](https://docs.subscriby.net/webhooks/v1/events/access-code): one code, one person, grants access.\n- [`payment.*`](https://docs.subscriby.net/webhooks/v1/events/payment): the payment a redemption rode in on.\n- [`subscription.*`](https://docs.subscriby.net/webhooks/v1/events/subscription): the subscription the discount bought.",
            "x-webhook-family": "coupon"
        },
        {
            "name": "referral.* events",
            "description": "Referral Program lifecycle, attribution and rewards. Fires as a creator sets up the programme, as members join it and hand out their codes, as the friends they bring in arrive and pay, and as the rewards those payments earn move from held to payable, paid out or reversed. A programme pays a referrer in free membership days or in a cash commission; Subscriby never moves that money. A commission is a figure the creator pays the affiliate themselves and then records here, so the ledger these events describe is the creator's, not a payment provider's.\n\nFour of these describe people and settings and are driven by the creator or the member. Six describe time and money: `referral.captured` and `referral.converted` are the attribution, `referral.reward_earned`, `referral.reward_approved` and `referral.reward_reversed` are the ledger, and `referral.payout_recorded` is the creator saying money left.\n\n| Event                          | Fires when                                                                      |\n| ------------------------------ | ------------------------------------------------------------------------------- |\n| `referral.program_updated`     | The programme's settings were written, with a list of what moved.               |\n| `referral.affiliate_joined`    | A member joined the programme, from the portal, a bot or the creator's hand.     |\n| `referral.affiliate_approved`  | A pending or suspended affiliate was approved and starts earning.               |\n| `referral.affiliate_suspended` | An affiliate was suspended and stops earning.                                   |\n| `referral.captured`            | A member arrived through an affiliate's link or typed their code.               |\n| `referral.converted`           | A referred member's first payment settled and locked the referral.              |\n| `referral.reward_earned`       | A settled payment earned the referrer, or the friend, days or money.            |\n| `referral.reward_approved`     | A held commission's refund window passed and it became payable.                 |\n| `referral.reward_reversed`     | A full refund reversed a commission, or clawed back one already paid.           |\n| `referral.payout_recorded`     | The creator recorded a payout to an affiliate.                                  |\n\n## The affiliate events nest an `affiliate` snapshot\n\n`affiliate_joined`, `affiliate_approved` and `affiliate_suspended` all carry the same nested object under `data.affiliate`, beside the member's id and the new standing, so one consumer can handle all three:\n\n```json\n{\n  \"affiliate\": {\n    \"id\": \"0d1e6a2f-5c83-4b9d-9c21-7e01d6a2f594\",\n    \"code\": \"K7PMQ2X\",\n    \"status\": \"approved\",\n    \"subscriber_id\": \"2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80\",\n    \"days_balance\": 0,\n    \"joined_at\": \"2026-11-20T09:14:02+00:00\",\n    \"approved_at\": \"2026-11-20T09:14:02+00:00\"\n  },\n  \"subscriber_id\": \"2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80\",\n  \"status\": \"approved\"\n}\n```\n\n> **The snapshot never carries payout details.** How an affiliate wants to be paid (a PayPal address, a wallet) is stored encrypted for the creator's dashboard and travels in no event, no broadcast and no log. Read it from the dashboard when you record a payout.\n\n## Money is a decimal string, days are an integer\n\n`amount` fields are decimal strings with four decimal places (`\"10.0000\"`), never numbers: parse them as decimals, as with every amount Subscriby sends. A clawback is a **negative** amount. `days` is an integer and is `null` on a money row; `amount` and `currency_id` are `null` on a days row.\n\n## Required ability\n\nEvery event in this family requires `project-referral:view` at token mint time.\n\n## Related\n\n- [`payment.*`](https://docs.subscriby.net/webhooks/v1/events/payment): the payment a reward rode in on; `payment.refunded` is what reverses one.\n- [`coupon.*`](https://docs.subscriby.net/webhooks/v1/events/coupon): a friend reward given as a coupon shows up as `coupon.redeemed`.\n- [`subscription.*`](https://docs.subscriby.net/webhooks/v1/events/subscription): the subscription a referred member bought.",
            "x-webhook-family": "referral"
        },
        {
            "name": "partner.* events",
            "description": "The Partner Program as it moves: a creator a partner brought to Subscriby signing up, their first paid plan converting the referral, the commission each of their invoices earns moving from held to payable, settled as Subscriby Credit or paid out in cash, and reversed when the money comes back. The programme is Subscriby's own, so the ledger these events describe is Subscriby's: a partner earns a share of what the creators they referred pay Subscriby, and Subscriby Credits or pays it.\n\nEvery event in this family is about the partner's own account, never a project: `project_id` is `null` and the event is delivered to the endpoints of the partner's current team. Two describe the standing (`partner.application_approved` and `partner.application_rejected`), one the rate (`partner.rate_changed`), two attribution (`partner.referral_signed_up` and `partner.referral_converted`), four the ledger (`partner.reward_earned`, `partner.reward_approved`, `partner.reward_credited` and `partner.reward_reversed`), and `partner.payout_recorded` is Subscriby saying money left.\n\n| Event                          | Fires when                                                                                          |\n| ------------------------------ | --------------------------------------------------------------------------------------------------- |\n| `partner.application_approved` | Subscriby approved the creator's application: their code and their starting rate exist from here.   |\n| `partner.application_rejected` | Subscriby turned the application down, with the reason and the day they may apply again.            |\n| `partner.rate_changed`         | The partner's commission rate moved: a commitment was verified or lapsed, or a volume tier was reached. |\n| `partner.referral_signed_up`  | A new creator account arrived through the partner's link, typed code or bot deep link.              |\n| `partner.referral_converted`  | The referred creator's first paid Starter or Growth invoice settled and locked the commission.       |\n| `partner.reward_earned`       | A paid invoice inside the commission period earned the partner a commission, held behind the hold.  |\n| `partner.reward_approved`     | A held commission's hold passed and it became payable.                                              |\n| `partner.reward_credited`     | A payable commission was applied to the partner's Subscriby balance.                                |\n| `partner.reward_reversed`     | A full refund, a dispute or a rejected review reversed a commission, or clawed back a settled one.   |\n| `partner.payout_recorded`     | Subscriby recorded a cash payout to the partner.                                                    |\n\n## The rate is a ladder, and a referral keeps the rate it was promised\n\nEvery approved partner starts at 5% of every invoice's total before tax, for 12 months from each conversion. Each promotion commitment Subscriby verifies (a long-form video review worth up to 10 points; a short video, a comparison article or a case study up to 5; a partner link in a community's public description up to 3) adds its points scaled by the reach of the audience it was done on, one the application declared for a channel the commitment fits: nothing below 10,001 followers, half from there, then 60%, 70%, 80% and 90% per band up to the full points over 1,000,000. Reaching 10 and 25 paying referrals adds 5 points each, and the sum is capped at 30%. An approved partner may add a commitment the application did not make, from the Partner Program page, on a declared audience or a new one above the floor; its proof is due 60 days from the day it was added and the rate moves only when it is verified. Rates are never negotiated: the ladder alone sets them. The points of a verified commitment are frozen at verification, at the band the owner judged the channel to be in. The partner's current rate is copied onto a referral at conversion and every reward it earns is priced from it. A **raise** is also written onto every referral still inside its commission period, because a partner is owed the rate they reached on every creator they brought. A **drop** happens only when a verified commitment's work vanishes or goes private and its points are withdrawn: the rate comes back down on every referral still inside its period, and every commission not yet credited or paid out is recalculated at the lower rate (`partner.reward_earned` rows keep their ids; their `amount` changes and the row carries the note `repriced`); money already credited or paid out stays where it went. `partner.rate_changed` fires on every move.\n\n## Money is a decimal string in USD\n\n`amount` and `base_amount` are decimal strings with four decimal places (`\"9.3600\"`), never numbers: parse them as decimals, as with every amount Subscriby sends. Platform invoices are billed in USD, so `currency` is always `USD`. A clawback is a **negative** amount. `base_amount` is the invoice's total before tax and after any discount, the figure the commission was taken from.\n\n## Required ability\n\nEvery event in this family requires `account:read` at token mint time.",
            "x-webhook-family": "partner"
        },
        {
            "name": "copilot_credit.* events",
            "description": "Copilot Credits as they move: a pack bought and credited, free credit granted, the balance running low, and a refund taking credit back. Copilot Credits are the prepaid pool Subscriby Copilot is metered through, kept in Subscriby's own ledger in US cents: paid packs and free grants side by side, the free part spent first. They never touch the Stripe customer balance, so a pack can never pay a plan invoice and a plan invoice can never consume them.\n\nEvery event in this family is about the creator's own account, never a project: `project_id` is `null` and the event is delivered to the endpoints of the creator's current team. Two describe money in (`copilot_credit.purchased` and `copilot_credit.granted`), one the balance (`copilot_credit.low`) and one money out (`copilot_credit.refunded`). Usage itself is not announced: a turn is too frequent for a webhook, and the balance it leaves is on every other event.\n\n| Event                       | Fires when                                                                                     |\n| --------------------------- | ---------------------------------------------------------------------------------------------- |\n| `copilot_credit.purchased` | Stripe reported a pack paid and its grants were written, at Checkout or by the auto top-up.    |\n| `copilot_credit.granted`   | Free Copilot Credits were granted: the welcome credit at sign-up, a promotion or goodwill.     |\n| `copilot_credit.low`       | A unit of usage left the balance under the low-balance threshold, once a day at most.          |\n| `copilot_credit.refunded`  | Stripe refunded the charge for a pack, in part or in full, and the credit was taken back.      |\n\n## Amounts are integers in cents\n\nEvery amount is an integer number of US cents (`2500` is $25.00), never a decimal string, because the pool is kept in cents. `balance_cents` is the whole balance after the event, free and paid together; it can be negative after a refund of credit already spent, which is the state in which the Copilot stops until a later grant covers it.\n\n## Required ability\n\nEvery event in this family requires `account:read` at token mint time.",
            "x-webhook-family": "copilot_credit"
        },
        {
            "name": "knowledge.* events",
            "description": "What a project teaches Subscriby Copilot, as it changes: an entry taught, an entry changed, an entry taken back. **Knowledge** is the page where a project writes down what only it knows, questions with their answers and guides, each cut into passages the Copilot is handed when a question matches; an entry marked for members lets the Copilot answer a member from it, in the inbox, the project bot and the portal chat, and an entry kept to the team serves the creator's own surfaces alone.\n\nEvery event in this family is about one project's Knowledge: `project_id` names it and the event is delivered to the endpoints of the project's team. The `entry` object names the entry and says what it is; it never carries the text.\n\n| Event               | Fires when                                                                                              |\n| ------------------- | ------------------------------------------------------------------------------------------------------- |\n| `knowledge.created` | An entry was saved and its passages reached the index, from the dashboard, the API or an MCP tool.      |\n| `knowledge.updated` | An entry's title, audience or text changed; silent when a save changed nothing.                         |\n| `knowledge.deleted` | An entry was removed with its passages and its file.                                                    |\n\n## The text never travels\n\nNo `knowledge.*` payload carries the entry's `body`. That is deliberate: webhook deliveries are logged and retried, and what a creator wrote down for the Copilot, a team's private notes included, does not belong in a delivery log. Read the entry over the API when the words matter.\n\n## Required ability\n\nEvery event in this family requires `project-knowledge:view` at token mint time.",
            "x-webhook-family": "knowledge"
        },
        {
            "name": "link.* events",
            "description": "Smart Link lifecycle. Fires as a creator authors, changes and retires the named, tracked addresses that bring members into a project. A Smart Link is one address per channel (a video description, a bio, a newsletter, a flyer's QR) whose clicks, and the members, purchases and payments behind them, are counted apart from every other channel's. Clicks and attributions carry no event of their own: a click is too frequent and too anonymous to be worth a webhook, and a member's source rides on the member wherever the member is read.\n\nAll three describe the link itself and are driven by the creator. The figures a link has earned are read from the funnel endpoints, never pushed.\n\n| Event           | Fires when                                                              |\n| --------------- | ----------------------------------------------------------------------- |\n| `link.created`  | A new Smart Link was authored, carrying its address and code.           |\n| `link.updated`  | A link's name, address, destination or expiry changed, with what moved. |\n| `link.archived` | A link was put out of use; its figures stay.                            |\n\n## Every event nests a `link` snapshot\n\n`created`, `updated` and `archived` all carry the same nested object under `data.link`, so one consumer can handle all three:\n\n```json\n{\n  \"link\": {\n    \"id\": \"7c2e5a90-3f41-4b8d-9e62-1a0d4c8b7f35\",\n    \"name\": \"YouTube description\",\n    \"slug\": \"youtube\",\n    \"code\": \"K7PMQ2X\",\n    \"destination\": \"plan\",\n    \"plan_id\": \"2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80\",\n    \"url\": \"https://my.subscriby.net/jane/go/youtube\",\n    \"expires_at\": null,\n    \"archived_at\": null,\n    \"clicks_total\": 0\n  }\n}\n```\n\n> **The slug may change; the code never does.** `url` is built from the slug and is the address a person reads. `code` is what the attribution cookie and the bot's `via_` start payload carry, so a printed QR or a shared bot link keeps working after the creator renames the address. Store the id, display the url, and never derive one from the other.\n\n## Destinations\n\n`destination` is one of `portal` (the project's plan list), `plan` (the checkout of the plan in `plan_id`) or `bot` (a conversation with the project's bot). `plan_id` is set only on a plan destination. A plan destination whose plan is later deleted, and a bot destination on a project with no bot, both land on the portal home rather than on an error page, so a printed link never breaks.\n\n## Required ability\n\nEvery event in this family requires `project-link:view` at token mint time.\n\n## Related\n\n- [`member.*`](https://docs.subscriby.net/webhooks/v1/events/member): the members a link brings, whose source is read on the member.\n- [`subscription.*`](https://docs.subscriby.net/webhooks/v1/events/subscription): the purchases the funnel counts as checkouts.\n- [`payment.*`](https://docs.subscriby.net/webhooks/v1/events/payment): the payments the funnel counts as revenue.",
            "x-webhook-family": "link"
        },
        {
            "name": "subscription.* events",
            "description": "Every transition across the subscription statuses, plus upgrade / downgrade. The busiest event family. Subscribe to these to drive CRM timelines, revenue dashboards, churn-risk pipelines, and Slack alerts.\n\n| Event                           | Fires when                                                                                                                |\n| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |\n| `subscription.created`          | An access code is redeemed, or a cardless trial starts. **Never** a paid checkout.                                        |\n| `subscription.activated`        | A paid subscription is acquired. Fires once, on the first successful payment.                                             |\n| `subscription.trial_started`    | A trial-enabled plan starts its free window.                                                                              |\n| `subscription.trial_converting` | A trial is about to convert. Fires 24h before conversion.                                                                 |\n| `subscription.trial_expired`    | A trial ended without converting.                                                                                         |\n| `subscription.renewed`          | Recurring billing charges the subscriber successfully.                                                                    |\n| `subscription.reactivated`      | A cancelled subscription is re-activated before `ends_at`.                                                                |\n| `subscription.paused`           | Subscription paused by creator or subscriber.                                                                             |\n| `subscription.unpaused`         | A paused subscription resumes.                                                                                            |\n| `subscription.past_due`         | Billing fails but grace period is active.                                                                                 |\n| `subscription.unpaid`           | Billing permanently failed; grace expired.                                                                                |\n| `subscription.cancelled`        | Cancellation recorded, access continues until `ends_at`.                                                                  |\n| `subscription.expired`          | `ends_at` reached; access revoked.                                                                                        |\n| `subscription.refunded`         | The whole charge came back; the subscription is expired and access revoked. Partial refunds emit `payment.refunded` only. |\n| `subscription.upgraded`         | Subscriber moved to a higher-priced plan.                                                                                 |\n| `subscription.downgraded`       | Subscriber moved to a lower-priced plan.                                                                                  |\n| `subscription.payment_recovered` | The next settled charge, or the rail's own status, closed a failed renewal's grace clock.                                |\n| `subscription.access_suspended` | A grace window closed unpaid; access is paused while the rail keeps retrying.                                             |\n| `subscription.access_restored`  | A paused member's charge settled; their links were reissued and they were welcomed back.                                  |\n| `subscription.cancellation_feedback` | A cancelling member said why, before deciding on the offer.                                                          |\n| `subscription.offer_taken`      | A cancelling member took the pause, the discount or the return coupon.                                                    |\n\n## Example payload\n\n`subscription.*` payloads carry flat identifier fields, not nested `subscription` / `plan` / `subscriber` objects. Every event in the family includes `subscription_id` and `subscriber_id`. All of them except `subscription.upgraded` and `subscription.downgraded` also include `plan_id`; those two carry `from_plan_id` and `to_plan_id` instead. The remaining keys vary per event, so check the individual event.\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"subscription.activated\",\n  \"created_at\": \"2026-05-18T10:05:00Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n  \"data\": {\n    \"subscription_id\": \"5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4\",\n    \"plan_id\": \"c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b\",\n    \"subscriber_id\": \"2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80\",\n    \"provider\": \"stripe\"\n  }\n}\n```\n\nPlan pricing, subscriber identity, and period boundaries are not embedded. Resolve them with [the subscription endpoint](https://docs.subscriby.net/api/v1/reference/subscriptions) and [the member endpoint](https://docs.subscriby.net/api/v1/reference/members).\n\n## Guarantees\n\n- Every acquisition emits exactly one of `subscription.activated` (paid) or `subscription.created` (access code, cardless trial), never both. Subscribe to both and de-duplicate on `data.subscription_id` to cover all acquisition paths.\n- `subscription.activated` fires at most once per subscription. Renewals emit `subscription.renewed` instead.\n- Out-of-order delivery is possible during retries. Use `SB-Event-Id` to de-dupe and `created_at` to sequence.\n\n## Required abilities\n\nTokens subscribing to `subscription.*` events must carry `project-subscription:view`.",
            "x-webhook-family": "subscription"
        },
        {
            "name": "sequence.* events",
            "description": "Recovery sequence lifecycle, and a member's passage through one. A sequence is the ordered messages a creator writes for one of four moments, a member who left, a new lead, a stalled checkout or a trial ending: each step goes out a set number of days after the one before it, in the creator's words with five placeholders filled per member, with the way back as a button and, if the creator chose one, a coupon. The first three events describe the sequence itself and are driven by the creator; the other four follow one member's passage from enrolment to the end, driven by the hourly sweep and by the member's own payments.\n\nA sequence runs only while the project's owner is on the Growth plan or holds the Revenue Recovery Addon. Without it nobody new is enrolled and no step goes out, and the sequences a creator built keep their place until the plan returns.\n\n| Event                 | Fires when                                                                                               |\n| --------------------- | -------------------------------------------------------------------------------------------------------- |\n| `sequence.created`    | A creator built a sequence, with no steps yet.                                                           |\n| `sequence.updated`    | A sequence was renamed, switched on or off, or a step was added, rewritten or removed.                   |\n| `sequence.deleted`    | A creator deleted a sequence; its members were let go first and its history stays.                       |\n| `sequence.enrolled`   | A member entered a running sequence because its trigger fired for them.                                  |\n| `sequence.step_sent`  | One step reached a member on their connected account.                                                    |\n| `sequence.converted`  | A member in a sequence paid again, so the passage ended as a win.                                        |\n| `sequence.exited`     | A passage ended before its last step for a reason other than a payment.                                  |\n\n## Every lifecycle event nests a `sequence` snapshot\n\n`created`, `updated` and `deleted` carry the same nested object under `data.sequence`, so one consumer can handle all three. The steps are listed in order, positions contiguous from 1:\n\n```json\n{\n  \"sequence\": {\n    \"id\": \"3e9a7c21-5d84-4f06-b2c1-8a7e5d4f9b02\",\n    \"name\": \"Win-back after churn\",\n    \"trigger\": \"churned\",\n    \"active\": true,\n    \"steps\": [\n      { \"id\": \"6b1f3d58-9c2a-4e7d-a0f4-2d8c7b5e1a93\", \"position\": 1, \"delay_days\": 3, \"coupon_id\": null },\n      { \"id\": \"9d4e2a07-1b6c-4f58-8e3a-5c7f0d2b9e41\", \"position\": 2, \"delay_days\": 7, \"coupon_id\": \"c2d8e4f1-7a3b-4c9d-b5e6-1f0a9d8c7b65\" }\n    ],\n    \"created_at\": \"2026-10-22T09:30:00+00:00\",\n    \"updated_at\": \"2026-10-22T09:45:00+00:00\",\n    \"deleted_at\": null\n  }\n}\n```\n\n> **A step's words never travel.** The snapshot carries each step's position, delay and coupon, not its message: the message is the creator's text with placeholders, filled per member at send time, and belongs on the dashboard.\n\n## Triggers\n\n`trigger` is what enrols a member: `churned`, their last live membership in the project ended; `lead`, they arrived without buying; `stalled_checkout`, a checkout they started stayed open past the project's window; `trial_ending`, a trial without a card is about to end. Each has its own listener or hourly sweep, and a sequence runs on one of them.\n\n## Required ability\n\nEvery event in this family requires `project-sequence:view` at token mint time.\n\n## Related\n\n- [`member.*`](https://docs.subscriby.net/webhooks/v1/events/member): `member.churned` fires the churn trigger and `member.lead_created` the lead trigger.\n- [`checkout.*`](https://docs.subscriby.net/webhooks/v1/events/checkout): the stall that fires the stalled-checkout trigger, and the recovery that converts its passage.\n- [`subscription.*`](https://docs.subscriby.net/webhooks/v1/events/subscription): the membership that ended, and the one a won-back member buys.\n- [`payment.*`](https://docs.subscriby.net/webhooks/v1/events/payment): the settled charge that converts a passage.\n- [`coupon.*`](https://docs.subscriby.net/webhooks/v1/events/coupon): the coupons a step may carry.",
            "x-webhook-family": "sequence"
        },
        {
            "name": "payment.* events",
            "description": "Payment lifecycle: succeeded, failed, pending, refunded. `payment.succeeded` and `payment.failed` are emitted by the provider webhook listeners, which all funnel through the same shared listener so their shapes stay consistent. `payment.pending` is emitted earlier, by the per-provider checkout-initiation actions, and its shape varies by provider. `payment.refunded` is emitted by a single shared refund action. Not every provider emits every event; see the per-event sections.\n\n| Event               | Fires when                                                                                                                                               |\n| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `payment.succeeded` | A payment provider confirms a successful charge.                                                                                                         |\n| `payment.failed`    | A provider rejects a charge (invalid card, insufficient funds, risk rules).                                                                              |\n| `payment.pending`   | A checkout is initiated and the subscriber is sent to the provider; the charge is not yet confirmed. Fires for every provider, including card checkouts. |\n| `payment.refunded`  | A charge is refunded, fully or partially.                                                                                                                |\n\n## Example envelope\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"payment.succeeded\",\n  \"created_at\": \"2026-05-18T10:05:00Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n  \"data\": {\n    \"subscription_id\": \"5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4\",\n    \"plan_id\": \"c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b\",\n    \"subscriber_id\": \"2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80\",\n    \"provider\": \"stripe\",\n    \"external_payment_id\": \"pi_3Nxy..\",\n    \"amount\": \"29.00\",\n    \"currency\": \"USD\",\n    \"billing_reason\": \"subscription_create\"\n  }\n}\n```\n\n## What you don't get\n\n- **Card numbers / PAN / CVV.** Any provider-specific credentials are stripped.\n- **Stripe raw webhook payloads.** Use Stripe's own webhooks if you need provider internals.\n- **Merchant fee breakdowns.** Those are an internal accounting concern surfaced only in the Subscriby dashboard.\n\n## Required ability\n\nTokens subscribing to `payment.*` events must carry `project-subscription:view` at mint time.",
            "x-webhook-family": "payment"
        },
        {
            "name": "checkout.* events",
            "description": "The checkout ledger's two moments. Every checkout a member starts, on the portal or in a connector's bot, on any rail, is written down the moment the gateway's page or invoice is handed over (`payment.pending` announces the start); the hourly sweep counts it as stalled once the project's window has passed with no settled charge and no live membership, and the next charge that settles for the member completes it. These two events are the stall and the recovery; the start is `payment.pending`.\n\n| Event                | Fires when                                                                                                             |\n| -------------------- | ---------------------------------------------------------------------------------------------------------------------- |\n| `checkout.stalled`   | A checkout stayed open past the project's window, and its member was enrolled in the stalled-checkout sequences.      |\n| `checkout.recovered` | A charge settled for the member after their checkout had stalled, whichever door they finally paid through.           |\n\n## Guarantees\n\n- A member is counted as stalled at most once a day, however many times they tapped Pay: later open starts inside that day are stamped quietly and raise nothing.\n- A member who holds a live membership by the time the window passes paid through another door; their open checkouts close quietly and raise nothing.\n- `checkout.recovered` fires once per stalled checkout, on the first charge that settles for the member afterwards. Checkouts that never stalled close on that charge too, silently.\n- The window is the project's `checkout_stall_hours` setting (1 to 24 hours, 1 by default), read at the sweep; a change applies to the checkouts still open.\n\n## Required ability\n\nTokens subscribing to `checkout.*` events must carry `project-subscription:view` at mint time, the ability the payment and subscription families need.\n\n## Related\n\n- [`payment.*`](https://docs.subscriby.net/webhooks/v1/events/payment): `payment.pending` is the start of every checkout, and `payment.succeeded` the charge that completes one.\n- [`sequence.*`](https://docs.subscriby.net/webhooks/v1/events/sequence): the passage a stall opens (`sequence.enrolled` with `trigger` `stalled_checkout`) and how it ends (`sequence.converted`).\n- [`subscription.*`](https://docs.subscriby.net/webhooks/v1/events/subscription): the membership a recovered checkout became.",
            "x-webhook-family": "checkout"
        },
        {
            "name": "member.* events",
            "description": "Member (subscriber) lifecycle events. A \"member\" in webhook events is the project-scoped subscriber, not a team member. Fires on arriving as a lead, joining, churning, bans, access grants and revocations, and the accounts a member connects on the connectors.\n\n| Event                      | Fires when                                                                                                                                                                                                        |\n| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `member.lead_created`      | A member row was created as a lead: somebody opened the project's bot, a Smart Link, a referral link or the portal for the first time, or wrote to support, without buying. Never for a link adopted from a sibling project or written by a backfill. |\n| `member.joined`            | An access code is redeemed against a non-trial plan. **Not** paid checkouts.                                                                                                                                      |\n| `member.trial_joined`      | A cardless trial starts, or a code is redeemed against a trial plan.                                                                                                                                              |\n| `member.converted`         | A trial converts to a paying subscription (Stripe only).                                                                                                                                                          |\n| `member.churned`           | A subscriber's subscription ends without renewal.                                                                                                                                                                 |\n| `member.removed`           | A subscriber is removed without being banned (e.g., kicked for inactivity).                                                                                                                                       |\n| `member.banned`            | A creator bans a subscriber.                                                                                                                                                                                      |\n| `member.unbanned`          | A ban is lifted.                                                                                                                                                                                                  |\n| `member.kicked`            | A subscriber is ejected from the project without a ban: status goes to churned, active subscriptions are cancelled, and every resource grant is revoked.                                                          |\n| `member.resource_added`    | A subscriber is added to an additional resource (channel, group).                                                                                                                                                 |\n| `member.resource_pending`  | A subscriber is entitled to a resource on a connector they hold no account on yet; access is issued the moment they connect one.                                                                                  |\n| `member.resource_reissued` | A creator, an agent or the member's own refresh revokes the grant a subscriber holds on a resource so a fresh one can be issued.                                                                                  |\n| `member.resource_removed`  | A subscriber is removed from a specific resource.                                                                                                                                                                 |\n| `member.access_extended`   | A connector outage of an hour or more ended and its length was banked on the subscriber's purchase: a fixed-term purchase ends later now, a recurring one runs that much longer after its last paid period.       |\n| `member.identity_linked`   | A subscriber connects a platform account: from the portal, by a first sign-in through a connector, or by adopting one from a sibling project.                                                                     |\n| `member.identity_unlinked` | A connected platform account is removed from a subscriber, by them on the portal or by the creator over the API.                                                                                                  |\n\n## Example envelope\n\nSubscription-driven member events (`joined`, `trial_joined`, `converted`, `churned`, `resource_added`, `resource_removed`) carry flat identifier fields:\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"member.joined\",\n  \"created_at\": \"2026-05-18T10:05:00Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n  \"data\": {\n    \"subscription_id\": \"5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4\",\n    \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n    \"plan_id\": \"c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b\",\n    \"subscriber_id\": \"2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80\",\n    \"access_code\": \"SLATE-SUNDAY-4F2A9\"\n  }\n}\n```\n\nModeration events (`banned`, `unbanned`, `kicked`, `removed`) instead nest a `subscriber` object:\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"member.banned\",\n  \"created_at\": \"2026-05-18T10:05:00Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n  \"data\": {\n    \"subscriber\": {\n      \"id\": \"2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80\",\n      \"status\": \"banned\"\n    },\n    \"reason\": \"Spamming referral links\"\n  }\n}\n```\n\n`data.subscriber` carries the member's id and status only; resolve their connected accounts with [the member identities endpoint](https://docs.subscriby.net/api/v1/reference/members).\n\n## Guarantees\n\n- `member.joined` and `member.trial_joined` fire only for zero-payment acquisition: access-code redemptions and cardless trials. Paid checkouts emit `subscription.activated` with no `member.*` join event.\n- `member.trial_joined` accompanies `subscription.trial_started` on the cardless-trial and access-code paths.\n- `member.converted` fires at most once per trial conversion, and only for Stripe.\n- No `member.*` payload carries the subscriber's email. Resolve subscriber detail with [the member endpoint](https://docs.subscriby.net/api/v1/reference/members) using `subscriber_id`.\n- The members endpoint returns `email` (member-chosen and verified) and `billing_email` (taken from their payment provider, unverified). Both require a token with `project-user:view`.\n\n## Required ability\n\nTokens subscribing to `member.*` events must carry `project-user:view` at mint time.",
            "x-webhook-family": "member"
        },
        {
            "name": "creator_task.* events",
            "description": "A hand-arranged perk a subscriber bought becomes a task for the creator, and is done. A **creator task** is a grant no connector can give: a manual resource (a perk you hand over yourself: a file, a call, a seat in a place no bot manages). When a purchase entitles a subscriber to one, the access ledger records a `creator_task` grant and opens a task for the creator; when the creator marks it done, the grant is issued and the subscriber's access is announced like any other.\n\n| Event                    | Fires when                                                                                                            |\n| ------------------------ | --------------------------------------------------------------------------------------------------------------------- |\n| `creator_task.opened`    | A purchase entitles a subscriber to a manual resource. One event per resource, with the task the creator now owns.    |\n| `creator_task.completed` | The creator marks the task done, on the members page, over the API or from an agent. `member.resource_added` follows. |\n\n## Example envelope\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"creator_task.opened\",\n  \"created_at\": \"2026-09-12T10:05:30Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n  \"data\": {\n    \"task_id\": \"9e4b2c71-3d58-4a6f-b0e2-7c1d5f8a9b34\",\n    \"grant_id\": \"7d1c3e9a-2b64-4f0e-9a58-3c6b1d8e2f47\",\n    \"subscription_id\": \"5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4\",\n    \"subscriber_id\": \"2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80\",\n    \"resource_id\": \"b73c5f21-9d80-4a6e-8215-4f70ce13a9d6\",\n    \"resource_kind\": \"manual\",\n    \"instructions\": \"Give Ada Lovelace access to Welcome packet.\",\n    \"due_at\": null\n  }\n}\n```\n\n## Required ability\n\nTokens subscribing to `creator_task.*` events must carry `project-subscription:view` at mint time.\n\n## Related\n\n- [Creator Tasks](https://docs.subscriby.net/api/v1/reference/creator-tasks): list open tasks and complete one.\n- `member.resource_added`: raised for the grant once the task is done.",
            "x-webhook-family": "creator_task"
        },
        {
            "name": "connector.* events",
            "description": "A project's connectors as they are installed, connected, verified, configured and disconnected: the family every connector answers to.\n\nA project runs on **connectors**: the platforms it gates access on, sends messages through and takes payments from. Each one the project runs is an **installation**, and every move in an installation's life is announced here: it is installed (a pending row, no credentials yet), connected (the creator handed the connector its credentials), verified or probed (its state moved), configured (a declared setting changed), disconnected (the credentials wiped, the row kept) and uninstalled (its grants revoked and resources detached, the row still kept). The events name Subscriby ids and the connector key only; a platform's own identifiers, tokens and settings values never travel in a webhook.\n\n| Event                          | Fires when                                                                                                        |\n| ------------------------------ | ----------------------------------------------------------------------------------------------------------------- |\n| `connector.installed`          | A connector was installed on a project: a pending installation, no credentials yet.                               |\n| `connector.connected`          | The creator connected the installation with their credentials; it can act now.                                    |\n| `connector.status_changed`     | A probe or a verify moved the installation's state.                                                               |\n| `connector.outage_opened`      | The platform refused the live installation outright; plans that unlock a place on it are off sale.                |\n| `connector.outage_closed`      | The outage ended: recovered, replaced or uninstalled, with how long it ran.                                        |\n| `connector.outage_compensated` | The outage settled: how many members had its length banked on their purchase, and how many lost invites were re-sent. |\n| `connector.doctor_completed`   | The connector doctor ran and found something different from last time.                                           |\n| `connector.settings_updated`   | A declared setting of the installation changed; which ones, never the values.                                     |\n| `connector.disconnected`       | The installation was disconnected: credentials wiped, row kept, members untouched.                                |\n| `connector.uninstalled`        | The connector was uninstalled: grants revoked, resources detached, the row kept; with the counts.                 |\n\n## Read them together with the API\n\nThe `installation_id` in every payload is the `id` of the rows the [project's installations endpoint](https://docs.subscriby.net/api/v1/reference/connectors) lists, and `connector` is the key of a card in the connector directory. A consumer that keeps a mirror of a project's connectors applies these events to those rows.\n\n## Example envelope\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"connector.connected\",\n  \"created_at\": \"2026-09-12T10:06:00Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n  \"data\": {\n    \"connector\": \"telegram\",\n    \"installation_id\": \"3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40\",\n    \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n    \"display_name\": \"Research Bot\",\n    \"handle\": \"research_bot\"\n  }\n}\n```\n\n## Required ability\n\nEvery `connector.*` event requires `project-connector:view` on the subscribing token and carries the project's `project_id`.",
            "x-webhook-family": "connector"
        },
        {
            "name": "recovery.* events",
            "description": "The Disaster Recovery ledger as it moves: incidents opening and resolving, recoveries starting, finishing, failing and being undone, standbys kept and consumed, channels swapped and accounts relinked.\n\n**Disaster Recovery** watches a creator's sign-in account, every project's bot and every channel or group a project sells, and swaps in what it can when a ban lands. Everything it detects and everything it does is a row in the recovery ledger, and every row change is announced here. The events name Subscriby ids and the connector key only; a platform's own identifiers never travel in a webhook.\n\nEvery `recovery.*` event requires `project-recovery:view` on the subscribing token. Events about a project carry that project's `project_id`; events about the creator's own account (an account incident, an account relink) carry `project_id: null` and are delivered to the endpoints of the team the creator owns.\n\n| Event                               | Fires when                                                                                                                       |\n| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |\n| `recovery.incident_opened`          | A health probe finds the creator's account unreachable, a project's bot refused, or a channel gone or no longer administered.    |\n| `recovery.incident_resolved`        | A later probe finds the thing healthy again, or a recovery replaces it.                                                          |\n| `recovery.operation_started`        | A recovery of any kind begins. Once per operation, so swaps absorbed into a running channel recovery fire no second start.       |\n| `recovery.operation_completed`      | The recovery finishes and its changes stand.                                                                                     |\n| `recovery.operation_failed`         | The recovery fails before changing anything.                                                                                     |\n| `recovery.operation_reverted`       | The creator undoes a recovery inside its window; one event per swap put back, or one for an account relink.                     |\n| `recovery.standby_registered`       | A standby bot is registered for a project, or a standby chat is linked to a resource.                                            |\n| `recovery.standby_removed`          | A standby is removed by the creator, replaced by another, or used in a recovery.                                                 |\n| `recovery.installation_failed_over` | Automatic failover switches a project onto its standby bot without the creator, after the platform refused the live one.         |\n| `recovery.resource_failed_over`     | Automatic failover swaps a banned channel for its standby without the creator.                                                   |\n| `recovery.resource_replaced`        | The creator swaps a resource onto a replacement chat, in a recovery or on demand.                                                |\n| `recovery.identity_relinked`        | The creator's sign-in account is relinked to a newly detected account, or the backup account is switched in.                     |\n| `recovery.readiness_changed`        | The readiness checklist's state differs from the last one recorded, after a recovery event or the nightly pass.                  |\n\n## Example payload\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"recovery.resource_failed_over\",\n  \"created_at\": \"2026-09-12T03:19:42Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n  \"data\": {\n    \"operation_id\": \"9a4d2e71-5b38-4c6f-8e12-3d7c9b0a5f21\",\n    \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n    \"resource_id\": \"b73c5f21-9d80-4a6e-8215-4f70ce13a9d6\",\n    \"resource_title\": \"Lounge\",\n    \"connector\": \"telegram\",\n    \"replaced_at\": \"2026-09-12T03:19:41Z\"\n  }\n}\n```\n\n## Required ability\n\nTokens subscribing to `recovery.*` events must carry `project-recovery:view`.\n\n## Related\n\n- [Disaster Recovery endpoints](https://docs.subscriby.net/api/v1/reference/disaster-recovery): read the same ledger: incidents, operations with their undo state, the roll call, allowances and readiness.\n- [Disaster Recovery](https://docs.subscriby.net/disaster-recovery): what the program does and why.\n- [`project.resource.status_changed`](https://docs.subscriby.net/webhooks/v1/events/project/project-resource-status-changed): the health verdict that precedes a resources incident.",
            "x-webhook-family": "recovery"
        },
        {
            "name": "broadcast.* events",
            "description": "Message broadcast lifecycle: when a send starts, and what it delivered. Fires when a creator sends a message to a segment of their members through the project's connector. Two events bracket every send: one as it starts, carrying the audience and how many members it will reach, and one when it finishes, carrying the delivered and failed tallies.\n\nBoth fire for broadcasts started **anywhere**: the dashboard, the bot, the [REST API](https://docs.subscriby.net/api/v1/reference/broadcasts), a Zap or an n8n workflow. They are emitted by the sending job rather than by each entry point, so a broadcast triggered by automation is indistinguishable from one typed into the dashboard.\n\n| Event                 | Fires when                                                              |\n| --------------------- | ----------------------------------------------------------------------- |\n| `broadcast.queued`    | A broadcast started sending, with its audience and recipient count.     |\n| `broadcast.completed` | The send finished, with delivered and failed tallies.                   |\n\n## Audience segments\n\nThe `audience` field on both events is one of:\n\n| Value                           | Reaches                                                       |\n| ------------------------------- | ------------------------------------------------------------- |\n| `all`                           | Every member with a linked chat                               |\n| `customer`                      | Paying members                                                |\n| `trialing`                      | Members on a trial                                            |\n| `lead`                          | Members who started the bot but never subscribed              |\n| `churned`                       | Members whose subscription ended                              |\n| `expiring_soon`                 | Members whose access lapses inside `expiring_within_days`     |\n| `cancelled_still_active`        | Members who turned renewal off but have time left             |\n| `paused`                        | Members whose subscription is paused rather than ended        |\n| `trialing_cardless`             | Members on a trial with no card on file                       |\n| `all_pass_holders`              | Holders of any currently-active pass window                   |\n| `all_pass_holders_not_in_queue` | As above, but only those who have not tapped their invite yet |\n| `pass_holders`                  | Holders of **one** named window                               |\n| `pass_holders_not_in_queue`     | Holders of one named window who have not queued               |\n\nThe two single-window pass segments carry a `pass_window_id`; every other segment reports `pass_window_id: null`. The four pass segments require the passes capability: a project whose plan no longer includes it cannot address them, and the API refuses the send rather than silently reaching nobody.\n\n`expiring_soon` reports the horizon it used in `expiring_within_days`; every other segment reports `null`. Note that an **auto-renewing** subscription is never in this segment: a subscription's end date is rewritten on every renewal, so a date alone would describe the next invoice rather than an expiry.\n\n## Narrowing by plan\n\nAny segment except `lead` and the four pass segments can be narrowed to a single plan, and both events then carry that plan in `data.plan_id`. It composes with the segment rather than replacing it: `customer` plus a plan means people paying for that plan right now, `churned` plus a plan means people who held it and left. Segments that cannot be narrowed always report `plan_id: null`.\n\nThis matters for a consumer that counts sends per audience: two `broadcast.completed` events can now carry the same `audience` and describe different populations, and `plan_id` is what tells them apart.\n\n> A member is only ever a recipient if they have a chat on **that project's** bot. Members with no chat, or whose chat belongs to a different bot, are excluded, which is why a recipient count is often well below a project's total membership.\n\n## The message body is never in the payload\n\nNeither event carries the text that was sent. Broadcasts are not stored (a broadcast is a send, not a record) and a body is arbitrary creator content up to 4096 characters. Repeating it on every subscribed endpoint would hand it to integrations that only need to know a send happened.\n\nIf you need the copy alongside the outcome, send the broadcast through the [REST API](https://docs.subscriby.net/api/v1/reference/broadcasts) or a Zap and correlate on `project_id` and `created_at`.\n\n## What does not emit\n\nA broadcast that is refused never emits either event, because nothing was sent:\n\n- the project has no connected bot\n- the audience is unknown\n- the body is empty once reduced to the connector's HTML subset\n- a pass segment was requested by a project whose plan no longer includes passes\n- a single-window segment was requested with no window\n\nThe REST API and MCP tool reject all of these up front with a validation error. The dashboard and bot paths log and abort.\n\n## Required ability\n\nTokens subscribing to `broadcast.*` events must carry `broadcast:send` at mint time. There is no separate read ability: knowing that a broadcast went out, to whom and how many, is the same privilege as being able to send one.",
            "x-webhook-family": "broadcast"
        },
        {
            "name": "access_code.* events",
            "description": "Access-code batch generation, redemption, and expiry. Emitted at the batch level for generation (never per-code, to prevent fan-out) and per-code for redemption and expiry.\n\n| Event                   | Fires when                                                                   |\n| ----------------------- | ---------------------------------------------------------------------------- |\n| `access_code.generated` | A bulk-generate job completes. Carries the batch size, not individual codes. |\n| `access_code.redeemed`  | A code is successfully redeemed by a subscriber.                             |\n| `access_code.expired`   | A code passes its expiry window without being redeemed.                      |\n\n## Example envelope\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"access_code.redeemed\",\n  \"created_at\": \"2026-05-18T10:05:00Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n  \"data\": {\n    \"subscription_id\": \"5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4\",\n    \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n    \"plan_id\": \"c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b\",\n    \"subscriber_id\": \"2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80\",\n    \"access_code\": \"9c1a7b3f-5d80-4e62-a4f1-0b83d2e6c517\"\n  }\n}\n```\n\nThe `access_code` string is the full redeemed code, not a masked fragment. It is already consumed and cannot be redeemed again, but treat it as a customer identifier and avoid forwarding it to systems you do not control.\n\n## Why batch, not per-code\n\nA 10,000-code bulk generation would produce 10,000 webhook deliveries per subscribed endpoint otherwise. The `generated` event fires once per batch with the count, and the per-code events fire later as codes are actually used.\n\n## Required ability\n\nTokens subscribing to `access_code.*` events must carry `project-access-code:view` at mint time.",
            "x-webhook-family": "access_code"
        },
        {
            "name": "support.* events",
            "description": "Member support inbox: conversations opened, replied to, assigned and resolved. A member who sends your project bot something it does not recognise opens a **support conversation**. These events are how that traffic reaches a helpdesk, an ops channel or an on-call rota instead of sitting in the dashboard waiting to be noticed.\n\n> No `support.*` payload carries the message body. That is deliberate: webhook deliveries are logged and retried, and member text does not belong in a delivery log. Fetch the body from the [support conversations endpoints](https://docs.subscriby.net/api/v1/reference/support-inbox) or with the [`get_support_conversation`](https://docs.subscriby.net/mcp/v1/tools/support/get-support-conversation) MCP tool.\n\n| Event                            | Fires when                                                                                               |\n| -------------------------------- | -------------------------------------------------------------------------------------------------------- |\n| `support.conversation.opened`    | A member messages a project bot for the first time on a given channel.                                   |\n| `support.message.received`       | Any inbound member message, including the one that opened the conversation.                              |\n| `support.message.sent`           | A reply is recorded and queued for delivery. Never fires for internal notes.                             |\n| `support.conversation.assigned`  | A conversation is assigned to a team member, or an assignment is cleared.                                |\n| `support.conversation.resolved`  | A conversation is marked resolved from the dashboard, the API or an MCP tool.                            |\n| `support.conversation.reopened`  | A resolved conversation goes active again, usually because the member wrote back.                        |\n| `support.conversation.blocked`   | A creator blocks the member behind a conversation; their messages are dropped from then on.              |\n| `support.conversation.unblocked` | A block is lifted and the member can reach the inbox again.                                              |\n| `support.canned_reply.created`   | A saved reply is added to the project's picker.                                                          |\n| `support.canned_reply.updated`   | A saved reply's title, body, shortcut or position changes.                                               |\n| `support.canned_reply.deleted`   | A saved reply is removed from the picker.                                                                |\n| `support.settings.updated`       | The project's inbox settings change: enabled, relay mode, agent name, auto-reply or email notifications. |\n\n## One conversation per member, per channel\n\nThere is exactly one conversation per `(project, member, channel)`. It is a durable thread, not a per-session ticket, so:\n\n- `support.conversation.opened` fires **once** per member per channel, ever. Their second message and every message after it raises `support.message.received` only.\n- Resolving does not close the thread. The next inbound message reopens it and raises `support.conversation.reopened`.\n- A workflow that wants \"every new member question\" should listen to `support.message.received`, not `opened`.\n\n## Example payload\n\nEvery `support.*` event uses the standard envelope and a flat `data` object of identifiers:\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"support.message.received\",\n  \"created_at\": \"2026-08-20T10:05:00Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n  \"data\": {\n    \"message_id\": \"6c18f7a3-2e95-4d60-b47a-c093e5182b7f\",\n    \"conversation_id\": \"9e042b6f-5d81-4c37-a920-7b3e18cf6d45\",\n    \"project_id\": \"7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13\",\n    \"subscriber_id\": \"2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80\",\n    \"type\": \"text\",\n    \"has_attachments\": false\n  }\n}\n```\n\n## Guarantees\n\n- The member's message body, their platform identity and any attachment file ids are **never** in the payload. Resolve them over the API with `data.conversation_id`.\n- `support.message.received` and `support.conversation.opened` both fire on a member's first message, in that order of significance: treat `opened` as the \"new contact\" signal and `received` as the \"new question\" signal.\n- Internal notes raise no event at all. They are private remarks for your team and never reach the member or a webhook.\n- A message from a **blocked** member is dropped before any event fires, and cannot reopen a resolved thread.\n- Rate-limited inbound messages are dropped silently. A member flooding the bot produces no event storm.\n\n## Required abilities\n\nTokens subscribing to `support.*` events must carry `support-conversation:view`.\n\n## Related\n\n- [Support conversations endpoints](https://docs.subscriby.net/api/v1/reference/support-inbox)\n- [Support inbox guide](https://docs.subscriby.net/creators/support-inbox)\n- [Contacting support](https://docs.subscriby.net/subscribers/contacting-support): the member's side",
            "x-webhook-family": "support"
        },
        {
            "name": "team.* events",
            "description": "Team creation, rename, deletion, and membership changes. Creating a team, inviting a collaborator and changing a collaborator's role require the Growth tier or above. Withdrawal is deliberately not gated: `team.member.removed`, `team.deleted` and invitation withdrawal all still work on an account whose tier has lapsed, so those events can reach a Free or Starter account's endpoints.\n\n| Event                      | Fires when                                                                                   |\n| -------------------------- | -------------------------------------------------------------------------------------------- |\n| `team.created`             | A team is created, including the personal team created with a new account.                   |\n| `team.updated`             | A team is renamed. `name` is the only mutable field on a team.                               |\n| `team.deleted`             | A team is deleted. Projects scoped to it are detached (`team_id` becomes null), not deleted. |\n| `team.member.invited`      | An invitation is issued to a new collaborator.                                               |\n| `team.member.joined`       | An invited collaborator accepts and joins.                                                   |\n| `team.member.removed`      | A collaborator is removed from the team by its owner.                                        |\n| `team.member.role_changed` | A collaborator's role within the team changes.                                               |\n\n## Example envelope\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"team.member.joined\",\n  \"created_at\": \"2026-05-18T10:05:00Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": null,\n  \"data\": {\n    \"team_id\": \"a83f0d51-4c92-4b7e-8615-2fd9e70a3c86\",\n    \"user_id\": \"2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80\"\n  }\n}\n```\n\n`data` is flat and deliberately thin: ids, plus whatever the transition itself carries. It is not a snapshot of the team or the collaborator. Read [the team member endpoint](https://docs.subscriby.net/api/v1/reference/team-members) for the profile, which keeps a joined member's details behind the `team-member:view` ability. The one exception is `team.member.invited`, which carries the invitee's `email`: an invitee has no user record to look up yet, so the id-only rule cannot apply to it.\n\n`project_id` is always `null` for `team.*` events; these are account-level.\n\n## Required ability\n\nTokens subscribing to `team.*` events must carry `team:view` at mint time, including for the four `team.member.*` events. No webhook event requires `team-member:invite`; that ability governs sending an invitation, not receiving the event about one.",
            "x-webhook-family": "team"
        },
        {
            "name": "role.* events",
            "description": "Role create, update and delete. Creating and updating a role are Growth-tier capabilities; deleting is not.\n\n| Event          | Fires when                                              |\n| -------------- | ------------------------------------------------------- |\n| `role.created` | A new role is created within a team.                    |\n| `role.updated` | Role name or abilities change.                          |\n| `role.deleted` | A role that no collaborator currently holds is deleted. |\n\n## Example envelope\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"role.updated\",\n  \"created_at\": \"2026-05-18T10:05:00Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": null,\n  \"data\": {\n    \"team_id\": \"a83f0d51-4c92-4b7e-8615-2fd9e70a3c86\",\n    \"role_id\": \"d05e1a83-7c46-4f29-b613-8ae407c9d251\",\n    \"code\": \"plan-editor\",\n    \"name\": \"Plan Editor\"\n  }\n}\n```\n\n`project_id` is always `null` for `role.*` events; these are account-level.\n\n## Required ability\n\nTokens subscribing to `role.*` events must carry `role:view` at mint time.",
            "x-webhook-family": "role"
        },
        {
            "name": "group.* events",
            "description": "Groups bundle **collaborators** for access control: a named permission set that several people in a team share, and someone can be in more than one. They are not a way to bundle projects. Creating and updating a group are Growth-tier capabilities; deleting is not, and a member sync is gated only when it adds somebody.\n\n| Event                  | Fires when                                                                 |\n| ---------------------- | -------------------------------------------------------------------------- |\n| `group.created`        | A new group is created.                                                    |\n| `group.updated`        | A group is renamed, or its permission set is replaced.                     |\n| `group.members_synced` | The people in a group changed. Carries `added_ids` and `removed_ids`.      |\n| `group.deleted`        | A group is deleted. Members stay in the team but lose whatever it granted. |\n\n> **Renaming and re-staffing are separate events.** `group.updated` covers what the group *is*; `group.members_synced` covers who it applies *to*. A consumer mirroring access control needs the second one: before it existed, changing who a permission set applied to announced nothing while renaming the same group announced itself.\n\n## Example envelope\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"group.updated\",\n  \"created_at\": \"2026-05-18T10:05:00Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": null,\n  \"data\": {\n    \"team_id\": \"a83f0d51-4c92-4b7e-8615-2fd9e70a3c86\",\n    \"group_id\": \"1f68d92a-04c5-4e83-97b1-3d6a05e2f847\",\n    \"code\": \"core-community\",\n    \"name\": \"Core Community\"\n  }\n}\n```\n\n`project_id` is always `null` for `group.*` events; these are account-level.\n\n## Required ability\n\nTokens subscribing to `group.*` events must carry `group:view` at mint time.",
            "x-webhook-family": "group"
        },
        {
            "name": "billing.* events",
            "description": "The creator's own Subscriby subscription tier: trial conversion, invoices, payment failures, grace periods, lockdowns. These events describe the creator's billing relationship with Subscriby itself, not their subscribers' billing. Useful for building ops dashboards that watch for accounts heading into lockdown.\n\n| Event                          | Fires when                                                                                                                                                             |\n| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `billing.invoice_created`      | A new invoice is generated for the creator's Subscriby tier.                                                                                                           |\n| `billing.invoice_paid`         | An invoice is paid in full.                                                                                                                                            |\n| `billing.invoice_overdue`      | Stripe marks the creator's invoice uncollectible. Nothing fires merely because a due date passed.                                                                      |\n| `billing.payment_failed`       | A recurring charge against the creator's payment method fails.                                                                                                         |\n| `billing.trial_ending`         | The creator's platform trial is about to convert. Fires at each milestone on the reminder ladder.                                                                      |\n| `billing.grace_period_warning` | The creator is approaching lockdown. Read `days_until_lockdown`; it varies by plan tier.                                                                               |\n| `billing.account_locked`       | The account reaches its tier's past-due lockdown: day 30 on a paid tier, day 7 on Free or an unconverted trial. New signups are blocked on the project's portal pages. |\n| `billing.tier_upgraded`        | Creator upgrades to a higher Subscriby tier.                                                                                                                           |\n| `billing.tier_downgraded`      | Creator downgrades to a lower tier.                                                                                                                                    |\n| `billing.tier_cancelled`       | Creator cancels their Subscriby subscription.                                                                                                                          |\n\n## Example envelope\n\n```json\n{\n  \"id\": \"evt_01HX...\",\n  \"type\": \"billing.account_locked\",\n  \"created_at\": \"2026-05-18T10:05:00Z\",\n  \"api_version\": \"2026-05-01\",\n  \"project_id\": null,\n  \"data\": {\n    \"creator_id\": \"2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80\",\n    \"past_due_since\": \"2026-04-18T00:00:00Z\",\n    \"locked_at\": \"2026-05-18T00:00:00Z\"\n  }\n}\n```\n\n`project_id` is always `null` for `billing.*` events; these are account-level.\n\n## When you'd subscribe\n\nThe typical consumer is an **internal ops dashboard** or **Slack room**, not a subscriber-facing system. Subscriby also emails the creator via the existing notification channels for every one of these events.\n\n## Required ability\n\nTokens subscribing to `billing.*` events must carry `billing:read` at mint time. Writes (upgrade, downgrade, cancel) additionally need `billing:manage`.",
            "x-webhook-family": "billing"
        }
    ],
    "security": [
        {
            "bearerToken": []
        }
    ],
    "paths": {
        "/v1/projects/{project}/plans/{plan}/access-codes": {
            "get": {
                "operationId": "v1.access-codes.index",
                "description": "Pages the plan's codes, newest first, fifty per page unless you say otherwise. `status` narrows the list to `unredeemed`, `redeemed` or `expired` codes; the default `all` returns every state.\n\nRaw `access_code` values are **always masked** in API responses to the last 5 characters. Plaintext codes ship only through the creator dashboard CSV export or the per-code messages a batch can be delivered as.",
                "summary": "List a plan's access codes",
                "tags": [
                    "Access Codes"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "plan",
                        "in": "path",
                        "required": true,
                        "description": "The plan, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "description": "Which codes to list: `all` (the default), `unredeemed`, `redeemed` or `expired`. An unknown value reads as `all`.",
                        "schema": {
                            "type": "string",
                            "default": "all"
                        },
                        "example": "unredeemed"
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 15.",
                        "schema": {
                            "type": "integer",
                            "default": 15,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/AccessCodeResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                    "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                    "subscriber_id": null,
                                                    "code_masked": "******12345",
                                                    "expires_at": "2026-08-01T00:00:00Z",
                                                    "redeemed_at": null,
                                                    "created_at": "2026-05-18T10:05:00Z"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-access-code:view-any"
                ],
                "x-mcp-tools": [
                    "list_access_codes"
                ]
            }
        },
        "/v1/projects/{project}/plans/{plan}/access-codes/preview": {
            "get": {
                "operationId": "v1.access-codes.preview",
                "description": "Prices a batch of `quantity` codes without queuing it, so a caller can show the worst-case charge before generating.\n\n```bash\ncurl \"https://api.subscriby.net/v1/projects/$PROJECT/plans/$PLAN/access-codes/preview?quantity=50\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\n> **Generation is free.** The metered overage is billed at **redemption time**, and only when your tier's free access-code allotment is already exhausted. Hand out codes freely; you only pay for the ones subscribers actually activate beyond the free quota.\n\nThe preview and the bulk-generate endpoint both return this cost breakdown so callers can surface the worst case (\"if every one of these codes is redeemed, here is what you would owe\").",
                "summary": "Price a batch",
                "tags": [
                    "Access Codes"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "plan",
                        "in": "path",
                        "required": true,
                        "description": "The plan, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "quantity",
                        "in": "query",
                        "required": true,
                        "description": "How many codes the batch would hold, 1 to 1,000.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": 50
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The cost preview.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "anyOf": [
                                                {
                                                    "type": "object",
                                                    "properties": {
                                                        "free_remaining": {
                                                            "description": "Codes still covered by the tier's free allotment this cycle.",
                                                            "examples": [
                                                                3
                                                            ]
                                                        },
                                                        "chargeable_quantity": {
                                                            "description": "How many of the batch would be metered if every one were redeemed.",
                                                            "examples": [
                                                                47
                                                            ]
                                                        },
                                                        "cost": {
                                                            "type": "string",
                                                            "description": "The worst-case charge for `chargeable_quantity`, as a decimal string in the billing currency.",
                                                            "examples": [
                                                                "1.41"
                                                            ]
                                                        },
                                                        "exceeds_threshold": {
                                                            "type": "boolean",
                                                            "description": "Whether `cost` passes the confirmation threshold the dashboard warns at.",
                                                            "examples": [
                                                                false
                                                            ]
                                                        },
                                                        "threshold": {
                                                            "description": "That threshold, in the billing currency.",
                                                            "anyOf": [
                                                                {
                                                                    "type": "integer"
                                                                },
                                                                {
                                                                    "type": "number",
                                                                    "examples": [
                                                                        50
                                                                    ]
                                                                }
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "free_remaining",
                                                        "chargeable_quantity",
                                                        "cost",
                                                        "exceeds_threshold",
                                                        "threshold"
                                                    ]
                                                },
                                                {
                                                    "type": "object",
                                                    "properties": {
                                                        "free_remaining": {
                                                            "description": "Codes still covered by the tier's free allotment this cycle.",
                                                            "examples": [
                                                                3
                                                            ]
                                                        },
                                                        "chargeable_quantity": {
                                                            "type": "integer",
                                                            "description": "How many of the batch would be metered if every one were redeemed.",
                                                            "examples": [
                                                                47
                                                            ]
                                                        },
                                                        "cost": {
                                                            "type": "string",
                                                            "description": "The worst-case charge for `chargeable_quantity`, as a decimal string in the billing currency.",
                                                            "const": "0",
                                                            "examples": [
                                                                "1.41"
                                                            ]
                                                        },
                                                        "exceeds_threshold": {
                                                            "type": "boolean",
                                                            "description": "Whether `cost` passes the confirmation threshold the dashboard warns at.",
                                                            "examples": [
                                                                false
                                                            ]
                                                        },
                                                        "threshold": {
                                                            "description": "That threshold, in the billing currency.",
                                                            "anyOf": [
                                                                {
                                                                    "type": "integer"
                                                                },
                                                                {
                                                                    "type": "number",
                                                                    "examples": [
                                                                        50
                                                                    ]
                                                                }
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "free_remaining",
                                                        "chargeable_quantity",
                                                        "cost",
                                                        "exceeds_threshold",
                                                        "threshold"
                                                    ]
                                                },
                                                {
                                                    "type": "object",
                                                    "properties": {
                                                        "free_remaining": {
                                                            "type": "integer",
                                                            "description": "Codes still covered by the tier's free allotment this cycle.",
                                                            "examples": [
                                                                3
                                                            ]
                                                        },
                                                        "chargeable_quantity": {
                                                            "type": "integer",
                                                            "description": "How many of the batch would be metered if every one were redeemed.",
                                                            "examples": [
                                                                47
                                                            ]
                                                        },
                                                        "cost": {
                                                            "type": "string",
                                                            "description": "The worst-case charge for `chargeable_quantity`, as a decimal string in the billing currency.",
                                                            "const": "0",
                                                            "examples": [
                                                                "1.41"
                                                            ]
                                                        },
                                                        "exceeds_threshold": {
                                                            "type": "boolean",
                                                            "description": "Whether `cost` passes the confirmation threshold the dashboard warns at.",
                                                            "examples": [
                                                                false
                                                            ]
                                                        },
                                                        "threshold": {
                                                            "type": "number",
                                                            "description": "That threshold, in the billing currency.",
                                                            "examples": [
                                                                50
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "free_remaining",
                                                        "chargeable_quantity",
                                                        "cost",
                                                        "exceeds_threshold",
                                                        "threshold"
                                                    ]
                                                }
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "free_remaining": 3,
                                                "chargeable_quantity": 47,
                                                "cost": "1.41",
                                                "exceeds_threshold": false,
                                                "threshold": 50
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when `quantity` is missing or outside 1 to 1,000; `error.context.quantity` says so.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-access-code:view-any"
                ],
                "x-mcp-tools": [
                    "preview_access_code_cost"
                ]
            }
        },
        "/v1/projects/{project}/plans/{plan}/access-codes/bulk-generate": {
            "post": {
                "operationId": "v1.access-codes.bulk-generate",
                "description": "Queues a batch of codes for the plan and answers `202 Accepted` at once; the codes are written by a background job and delivered the way `export_type` names. Poll the list endpoint, or subscribe to `access_code.generated`, to know when the batch is ready.\n\n```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT/plans/$PLAN/access-codes/bulk-generate \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"quantity\": 50,\n    \"export_type\": \"file\",\n    \"expiry_preset\": \"1_month\"\n  }'\n```\n\nAnswers `202` with the job's key, the plan, the quantity and the cost preview the pricing endpoint describes. Bulk generation is limited to **10 batches per minute per token** in its own bucket, on top of the token's general limits; the eleventh answers `429 RATE_LIMITED` with `Retry-After`.\n\nThe validation rules are identical to the creator dashboard's: `quantity` 1 to 1,000; `export_type` `file` or `messages`, with `consent: true` required for `messages` because one bot message per code can trip the connector's rate limits; `expiry_preset` one of `no_expiry`, `1_day`, `1_week`, `1_month`, `1_year` or `custom`, the last needing `custom_expiry_amount` and `custom_expiry_type` (`days`, `weeks`, `months` or `years`).",
                "summary": "Generate a batch of codes",
                "tags": [
                    "Access Codes"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "plan",
                        "in": "path",
                        "required": true,
                        "description": "The plan, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BulkGenerateAccessCodesRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "202 with the job key, the plan, the quantity and the preview.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "unique_key": {
                                                    "type": "string",
                                                    "description": "The job's uniqueness key: a second batch for the same plan queued while one is running is folded into it.",
                                                    "examples": [
                                                        "user_plan_key"
                                                    ]
                                                },
                                                "plan_id": {
                                                    "type": "string",
                                                    "description": "The plan the codes activate.",
                                                    "examples": [
                                                        "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b"
                                                    ]
                                                },
                                                "quantity": {
                                                    "type": "integer",
                                                    "description": "How many codes were requested.",
                                                    "examples": [
                                                        50
                                                    ]
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "Always `generation_queued`.",
                                                    "const": "generation_queued",
                                                    "examples": [
                                                        "generation_queued"
                                                    ]
                                                },
                                                "preview": {
                                                    "description": "The worst-case cost breakdown, as the preview endpoint answers it.",
                                                    "anyOf": [
                                                        {
                                                            "type": "object",
                                                            "properties": {
                                                                "free_remaining": {
                                                                    "description": "Codes still covered by the tier's free allotment this cycle.",
                                                                    "examples": [
                                                                        3
                                                                    ]
                                                                },
                                                                "chargeable_quantity": {
                                                                    "description": "How many of the batch would be metered if every one were redeemed.",
                                                                    "examples": [
                                                                        47
                                                                    ]
                                                                },
                                                                "cost": {
                                                                    "type": "string",
                                                                    "description": "The worst-case charge for `chargeable_quantity`, as a decimal string in the billing currency.",
                                                                    "examples": [
                                                                        "1.41"
                                                                    ]
                                                                },
                                                                "exceeds_threshold": {
                                                                    "type": "boolean",
                                                                    "description": "Whether `cost` passes the confirmation threshold the dashboard warns at.",
                                                                    "examples": [
                                                                        false
                                                                    ]
                                                                },
                                                                "threshold": {
                                                                    "description": "That threshold, in the billing currency.",
                                                                    "anyOf": [
                                                                        {
                                                                            "type": "integer"
                                                                        },
                                                                        {
                                                                            "type": "number",
                                                                            "examples": [
                                                                                50
                                                                            ]
                                                                        }
                                                                    ]
                                                                }
                                                            },
                                                            "required": [
                                                                "free_remaining",
                                                                "chargeable_quantity",
                                                                "cost",
                                                                "exceeds_threshold",
                                                                "threshold"
                                                            ]
                                                        },
                                                        {
                                                            "type": "object",
                                                            "properties": {
                                                                "free_remaining": {
                                                                    "description": "Codes still covered by the tier's free allotment this cycle.",
                                                                    "examples": [
                                                                        3
                                                                    ]
                                                                },
                                                                "chargeable_quantity": {
                                                                    "type": "integer",
                                                                    "description": "How many of the batch would be metered if every one were redeemed.",
                                                                    "examples": [
                                                                        47
                                                                    ]
                                                                },
                                                                "cost": {
                                                                    "type": "string",
                                                                    "description": "The worst-case charge for `chargeable_quantity`, as a decimal string in the billing currency.",
                                                                    "const": "0",
                                                                    "examples": [
                                                                        "1.41"
                                                                    ]
                                                                },
                                                                "exceeds_threshold": {
                                                                    "type": "boolean",
                                                                    "description": "Whether `cost` passes the confirmation threshold the dashboard warns at.",
                                                                    "examples": [
                                                                        false
                                                                    ]
                                                                },
                                                                "threshold": {
                                                                    "description": "That threshold, in the billing currency.",
                                                                    "anyOf": [
                                                                        {
                                                                            "type": "integer"
                                                                        },
                                                                        {
                                                                            "type": "number",
                                                                            "examples": [
                                                                                50
                                                                            ]
                                                                        }
                                                                    ]
                                                                }
                                                            },
                                                            "required": [
                                                                "free_remaining",
                                                                "chargeable_quantity",
                                                                "cost",
                                                                "exceeds_threshold",
                                                                "threshold"
                                                            ]
                                                        },
                                                        {
                                                            "type": "object",
                                                            "properties": {
                                                                "free_remaining": {
                                                                    "type": "integer",
                                                                    "description": "Codes still covered by the tier's free allotment this cycle.",
                                                                    "examples": [
                                                                        3
                                                                    ]
                                                                },
                                                                "chargeable_quantity": {
                                                                    "type": "integer",
                                                                    "description": "How many of the batch would be metered if every one were redeemed.",
                                                                    "examples": [
                                                                        47
                                                                    ]
                                                                },
                                                                "cost": {
                                                                    "type": "string",
                                                                    "description": "The worst-case charge for `chargeable_quantity`, as a decimal string in the billing currency.",
                                                                    "const": "0",
                                                                    "examples": [
                                                                        "1.41"
                                                                    ]
                                                                },
                                                                "exceeds_threshold": {
                                                                    "type": "boolean",
                                                                    "description": "Whether `cost` passes the confirmation threshold the dashboard warns at.",
                                                                    "examples": [
                                                                        false
                                                                    ]
                                                                },
                                                                "threshold": {
                                                                    "type": "number",
                                                                    "description": "That threshold, in the billing currency.",
                                                                    "examples": [
                                                                        50
                                                                    ]
                                                                }
                                                            },
                                                            "required": [
                                                                "free_remaining",
                                                                "chargeable_quantity",
                                                                "cost",
                                                                "exceeds_threshold",
                                                                "threshold"
                                                            ]
                                                        }
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "unique_key",
                                                "plan_id",
                                                "quantity",
                                                "status",
                                                "preview"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "unique_key": "user_plan_key",
                                                "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "quantity": 50,
                                                "status": "generation_queued",
                                                "preview": {
                                                    "free_remaining": 3,
                                                    "chargeable_quantity": 47,
                                                    "cost": "1.41",
                                                    "exceeds_threshold": false,
                                                    "threshold": 50
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when a rule above is broken; `error.fields` names the key, and the `consent` and custom-expiry messages spell out what was missing.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "description": "`RATE_LIMITED`: the token has spent its 300 requests a minute or 10,000 an hour; `Retry-After` says when the next one is accepted.\n\nOn this endpoint: `RATE_LIMITED`: when the token has queued 10 batches within a minute.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RATE_LIMITED": {
                                        "summary": "RATE_LIMITED",
                                        "value": {
                                            "error": {
                                                "code": "RATE_LIMITED",
                                                "message": "The rate limit for this token has been exceeded.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#rate-limited",
                                                "remediation": "Back off and retry after the time hinted by the Retry-After header.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "x-required-scopes": [
                    "project-access-code:create"
                ],
                "x-webhook-events": [
                    "access_code.generated"
                ],
                "x-mcp-tools": [
                    "bulk_generate_access_codes"
                ]
            }
        },
        "/v1/projects/{project}/plans/{plan}/access-codes/{accessCode}": {
            "delete": {
                "operationId": "v1.access-codes.destroy",
                "description": "Deletes an unredeemed code so it can no longer be claimed. The code is resolved within the plan, so an id from another plan is `404 RESOURCE_NOT_FOUND`. Answers `204` with no body; no webhook fires.",
                "summary": "Revoke an access code",
                "tags": [
                    "Access Codes"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "plan",
                        "in": "path",
                        "required": true,
                        "description": "The plan, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "accessCode",
                        "in": "path",
                        "required": true,
                        "description": "The unredeemed code, resolved within the plan by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-access-code:delete"
                ],
                "x-mcp-tools": [
                    "revoke_access_code"
                ]
            }
        },
        "/v1/activity": {
            "get": {
                "operationId": "v1.activity.index",
                "description": "The newest entries recorded against one subject, `limit` at a time (50 by default, 200 at most), newest first. Name the subject by alias and id:\n\n```bash\ncurl \"https://api.subscriby.net/v1/activity?subject_type=project&subject_id=$PROJECT_ID&limit=20\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThere is no paging beyond `limit`: the endpoint is a recent-history read, not an export. The subject is resolved through its own tenant-scoped query before activity is read, so passing the id of a project (or subscription, plan, member) that belongs to another team returns `404 RESOURCE_NOT_FOUND` rather than an empty list; existence never leaks across tenants.\n\n- `subject_type` and `causer_type` use short morph aliases (`project`, `project-subscription`, `project-subscription-plan`, `project-user`, `project-resource`, `user`, …) rather than internal class names. Treat them as opaque strings. The `subject_type` **query parameter** accepts only the aliases listed on the endpoint; a class name is `422 VALIDATION_FAILED`.\n- `actor_kind` distinguishes the surface the change came through: `human` (dashboard click), `api_token` (REST), `mcp` (MCP tool), `zapier`, `webhook`, `system` (scheduled job). Filter on it client-side when you need \"everything the agent did yesterday\" separately from dashboard clicks.\n- `properties` keys matching `token`, `secret`, `password`, `api_key` or `api_secret` (case-insensitive) are stripped at any depth before the response leaves the server, so LLM context windows never see credentials that were logged alongside a write.",
                "summary": "Read a subject's activity",
                "tags": [
                    "Activity"
                ],
                "parameters": [
                    {
                        "name": "subject_type",
                        "in": "query",
                        "required": true,
                        "description": "The kind of subject, as a short alias: `project`, `subscription` (or `project-subscription`), `member` (or `project-user`), `plan` (or `project-subscription-plan`), `access-code`, `coupon` or `project-resource`. A class name is refused.",
                        "schema": {
                            "$ref": "#/components/schemas/ActivitySubjectType"
                        }
                    },
                    {
                        "name": "subject_id",
                        "in": "query",
                        "required": true,
                        "description": "The subject's id.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "How many of the newest entries to return, 1 to 200; defaults to 50. A value above 200 is refused rather than clamped.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 200
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Array of `ActivityResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "$ref": "#/components/schemas/ActivityResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "92e4c1b6-70da-4f38-8517-b036ae94d7c2",
                                                    "log_name": "default",
                                                    "description": "updated",
                                                    "event": "updated",
                                                    "subject_type": "project",
                                                    "subject_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                    "causer_type": "user",
                                                    "causer_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                    "actor_kind": "api_token",
                                                    "properties": {
                                                        "attributes": {
                                                            "name": "Research Premium"
                                                        },
                                                        "old": {
                                                            "name": "Research"
                                                        }
                                                    },
                                                    "created_at": "2026-05-18T10:05:00Z"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: when the subject does not exist in the caller's tenant, or belongs to a project outside the token's `scope:project:` allow-list.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `subject_type` or `subject_id` is missing, the alias is unknown, the id is not a UUID, or `limit` is above 200.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "activity:read"
                ],
                "x-mcp-tools": [
                    "get_activity_log"
                ]
            }
        },
        "/v1/me/alert-destinations": {
            "get": {
                "operationId": "v1.me.alert-destinations.index",
                "description": "Your destinations, primary first.\n\n- `kind` is `connector_identity` or `email` (`push_device` is reserved for the creator apps).\n- `target` is the connector account's id for `connector_identity`, the same value `GET /v1/me/identities` returns as the account behind a linked identity, or the email address for `email`.\n- `classes` lists the alert classes routed here, is `null` for every class, or is `[]` for none (the account is kept but receives nothing).\n- `is_primary` marks the destination of your primary connected account. It is derived from your linked identities, never set through this API.\n\nUntil you write a destination, you are on the **default**: every class of alert goes to your primary connected account, and the critical classes go to your email as well. The list is empty while the default applies, and the dashboard grid shows the default as every cell ticked on that account. Linking a primary account writes the default down as rows and adds the new account to them, so from then on the rows lead.\n\n> **Critical classes always reach your email.** Recovery, billing and security alerts are sent to your email whatever the destinations say, because they arrive when the connector you would otherwise read them on may have just failed. Routing them to a connected account adds a message there; it never removes the email.",
                "summary": "List your alert destinations",
                "tags": [
                    "Alert Destinations"
                ],
                "responses": {
                    "200": {
                        "description": "Array of `AlertDestinationResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "$ref": "#/components/schemas/AlertDestinationResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "5d3a9c1e-7f2b-4e8d-a1c6-9b0f3e2d4a71",
                                                    "kind": "connector_identity",
                                                    "target": "0c2d8a7e-4b1f-4d3e-9a6b-2f5e8c1d7a90",
                                                    "classes": [
                                                        "sales",
                                                        "support",
                                                        "passes"
                                                    ],
                                                    "is_primary": true,
                                                    "verified_at": "2026-09-12T10:05:00Z"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-mcp-tools": [
                    "get_alert_destinations"
                ]
            },
            "put": {
                "operationId": "v1.me.alert-destinations.update",
                "description": "Takes the complete list you want to keep; anything not in it is removed. Each entry names a `kind`, a `target` and optional `classes`:\n\n```bash\ncurl -X PUT https://api.subscriby.net/v1/me/alert-destinations \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"destinations\": [\n      { \"kind\": \"connector_identity\", \"target\": \"0c2d8a7e-4b1f-4d3e-9a6b-2f5e8c1d7a90\", \"classes\": [\"sales\", \"support\", \"passes\"] },\n      { \"kind\": \"email\", \"target\": \"ada@example.com\", \"classes\": null }\n    ]\n  }'\n```\n\nThe response is the resulting list. `PUT` is a replacement, not a patch: send an empty `destinations` list to remove every row and return to the default. `is_primary` in the payload is ignored; the service derives it from your linked identities.\n\nWhen a creator alert is sent, every connected account routed to its class receives a message through that connector, and email is used when an email destination routes the class, when no connected account does, or when the class is critical. The same routing decides whether the bot messages you at all about a sale, a waiting member or a pass window: a class you route away from an account is never sent there. A newly linked primary account receives a destination for every class automatically, so linking keeps working as it did; unlinking the account removes its destination.",
                "summary": "Replace your alert destinations",
                "tags": [
                    "Alert Destinations"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateAlertDestinationsRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Array of `AlertDestinationResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "$ref": "#/components/schemas/AlertDestinationResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: when a `target` is not one of your own linked accounts or your own address; nothing is written.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `destinations` is missing, holds more than 20 entries, or an entry has an unknown `kind` or class.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:write"
                ],
                "x-mcp-tools": [
                    "update_alert_destinations"
                ]
            }
        },
        "/v1/analytics/dashboard": {
            "get": {
                "operationId": "v1.analytics.dashboard",
                "description": "Total revenue, total transactions, total users and MRR, each with a trend relative to the `compare_period` window and a sparkline. The **Recurring Monthly Income** tile counts only active subscriptions on recurring plans, normalised to a monthly figure; one-time and lifetime plans are excluded.\n\n```bash\ncurl \"https://api.subscriby.net/v1/analytics/dashboard?period=30d&compare_period=previous\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```",
                "summary": "Headline figures",
                "tags": [
                    "Analytics"
                ],
                "parameters": [
                    {
                        "name": "project_id",
                        "in": "query",
                        "description": "Scope the figures to one project the token may see; omit for every project visible to it. A project outside the token's `scope:project:` allow-list is `404 TENANT_MISMATCH`, an unknown one `404 RESOURCE_NOT_FOUND`.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "period",
                        "in": "query",
                        "description": "The preset window: `7d`, `14d`, `30d` (the default), `60d`, `90d`, `mtd`, `qtd`, `ytd`, `1y` or `all`. Ignored when both `from` and `to` are given; an unknown value falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "30d"
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "description": "The first day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "description": "The last day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "compare_period",
                        "in": "query",
                        "description": "`previous` (the default) compares each tile with the window just before it and fills `trend`; `none` leaves the trend out.",
                        "schema": {
                            "type": "string",
                            "default": "previous"
                        }
                    },
                    {
                        "name": "plan_ids[]",
                        "in": "query",
                        "description": "Count only these plans. Send it as `plan_ids[]=a&plan_ids[]=b` or as one comma-separated string.",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    },
                    {
                        "name": "statuses[]",
                        "in": "query",
                        "description": "Count only payments in these states: `successful`, `failed`, `pending`, `refunded`. Send them as `statuses[]=a&statuses[]=b` or as one comma-separated string.",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    },
                    {
                        "name": "payment_method_ids[]",
                        "in": "query",
                        "description": "Count only payments taken through these payment methods. Send them as `payment_method_ids[]=a&payment_method_ids[]=b` or as one comma-separated string.",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The headline tiles.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "title": {
                                                        "type": "string",
                                                        "description": "The tile's name, in the creator's language.",
                                                        "examples": [
                                                            "Total Revenue"
                                                        ]
                                                    },
                                                    "value": {
                                                        "type": "string",
                                                        "description": "The formatted figure, USD-normalised for money.",
                                                        "examples": [
                                                            "$12,480.00"
                                                        ]
                                                    },
                                                    "trend": {
                                                        "type": "string",
                                                        "description": "The change against the comparison window as a percentage; absent when `compare_period` is `none`.",
                                                        "examples": [
                                                            "12.4%"
                                                        ]
                                                    },
                                                    "trendUp": {
                                                        "type": "boolean",
                                                        "description": "Whether the figure rose against the comparison window.",
                                                        "examples": [
                                                            true
                                                        ]
                                                    },
                                                    "charting": {
                                                        "type": "array",
                                                        "description": "The sparkline's points across the window, oldest first.",
                                                        "items": {
                                                            "anyOf": [
                                                                {
                                                                    "type": "number",
                                                                    "examples": [
                                                                        0
                                                                    ]
                                                                },
                                                                {
                                                                    "type": "integer",
                                                                    "examples": [
                                                                        0
                                                                    ]
                                                                }
                                                            ]
                                                        }
                                                    }
                                                },
                                                "required": [
                                                    "title",
                                                    "value",
                                                    "trend",
                                                    "trendUp",
                                                    "charting"
                                                ]
                                            }
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The window the figures were computed for, echoed back.",
                                            "properties": {
                                                "period": {
                                                    "type": "string",
                                                    "description": "The preset the window resolved from, as requested.",
                                                    "enum": [
                                                        "7d",
                                                        "14d",
                                                        "30d",
                                                        "60d",
                                                        "90d",
                                                        "1y",
                                                        "mtd",
                                                        "qtd",
                                                        "ytd",
                                                        "all"
                                                    ],
                                                    "examples": [
                                                        "30d"
                                                    ]
                                                },
                                                "compare_period": {
                                                    "type": "string",
                                                    "description": "`previous` or `none`, as requested.",
                                                    "examples": [
                                                        "previous"
                                                    ]
                                                },
                                                "project_id": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The project the figures were scoped to, or `null` for every project the token may see.",
                                                    "examples": [
                                                        null
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "period",
                                                "compare_period",
                                                "project_id"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "title": "Total Revenue",
                                                    "value": "$12,480.00",
                                                    "trend": "12.4%",
                                                    "trendUp": true,
                                                    "charting": [
                                                        0,
                                                        0,
                                                        120,
                                                        0,
                                                        340,
                                                        0,
                                                        720,
                                                        0,
                                                        0,
                                                        860
                                                    ]
                                                },
                                                {
                                                    "title": "Total Transactions",
                                                    "value": "342",
                                                    "trend": "8.1%",
                                                    "trendUp": true,
                                                    "charting": [
                                                        0,
                                                        0,
                                                        2,
                                                        0,
                                                        6,
                                                        0,
                                                        18,
                                                        0,
                                                        0,
                                                        22
                                                    ]
                                                },
                                                {
                                                    "title": "Total Users",
                                                    "value": "1,204",
                                                    "trend": "2.9%",
                                                    "trendUp": true,
                                                    "charting": [
                                                        0,
                                                        0,
                                                        0,
                                                        0,
                                                        1,
                                                        0,
                                                        4,
                                                        0,
                                                        0,
                                                        3
                                                    ]
                                                },
                                                {
                                                    "title": "Recurring Monthly Income",
                                                    "value": "$4,120.00",
                                                    "trend": "5.6%",
                                                    "trendUp": true,
                                                    "charting": [
                                                        0,
                                                        0,
                                                        120,
                                                        0,
                                                        340,
                                                        0,
                                                        720,
                                                        0,
                                                        0,
                                                        860
                                                    ]
                                                }
                                            ],
                                            "meta": {
                                                "period": "30d",
                                                "compare_period": "previous",
                                                "project_id": null
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "dashboard:read"
                ],
                "x-mcp-tools": [
                    "get_dashboard_metrics"
                ]
            }
        },
        "/v1/analytics/earnings": {
            "get": {
                "operationId": "v1.analytics.earnings",
                "description": "The full earnings breakdown (gross, fees, net, transaction count) plus a timeseries bucketed by `granularity`: `day` (the default), `week` or `month`.\n\n```bash\ncurl \"https://api.subscriby.net/v1/analytics/earnings?granularity=week\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nEvery money figure is USD-normalised so buckets in different currencies add up; `totals.currency` says so.",
                "summary": "Earnings report",
                "tags": [
                    "Analytics"
                ],
                "parameters": [
                    {
                        "name": "project_id",
                        "in": "query",
                        "description": "Scope the figures to one project the token may see; omit for every project visible to it. A project outside the token's `scope:project:` allow-list is `404 TENANT_MISMATCH`, an unknown one `404 RESOURCE_NOT_FOUND`.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "period",
                        "in": "query",
                        "description": "The preset window: `7d`, `14d`, `30d` (the default), `60d`, `90d`, `mtd`, `qtd`, `ytd`, `1y` or `all`. Ignored when both `from` and `to` are given; an unknown value falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "30d"
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "description": "The first day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "description": "The last day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "granularity",
                        "in": "query",
                        "description": "The bucket size of the timeseries: `day` (the default), `week` or `month`. Anything else is `422 VALIDATION_FAILED`.",
                        "schema": {
                            "type": "string",
                            "default": "day"
                        }
                    },
                    {
                        "name": "plan_ids[]",
                        "in": "query",
                        "description": "Count only these plans. Send it as `plan_ids[]=a&plan_ids[]=b` or as one comma-separated string.",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    },
                    {
                        "name": "statuses[]",
                        "in": "query",
                        "description": "Count only payments in these states: `successful`, `failed`, `pending`, `refunded`. Send them as `statuses[]=a&statuses[]=b` or as one comma-separated string.",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    },
                    {
                        "name": "payment_method_ids[]",
                        "in": "query",
                        "description": "Count only payments taken through these payment methods. Send them as `payment_method_ids[]=a&payment_method_ids[]=b` or as one comma-separated string.",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Gross, fees and net per bucket.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "range": {
                                                    "type": "object",
                                                    "description": "The window the preset resolved to, and how it was bucketed.",
                                                    "properties": {
                                                        "from": {
                                                            "type": "string",
                                                            "description": "The first day of the window, `YYYY-MM-DD`."
                                                        },
                                                        "to": {
                                                            "type": "string",
                                                            "description": "The last day of the window, `YYYY-MM-DD`."
                                                        },
                                                        "granularity": {
                                                            "type": "string",
                                                            "description": "`day`, `week` or `month`: how wide each timeseries bucket is."
                                                        }
                                                    },
                                                    "required": [
                                                        "from",
                                                        "to",
                                                        "granularity"
                                                    ]
                                                },
                                                "totals": {
                                                    "type": "object",
                                                    "description": "The whole window summed.",
                                                    "properties": {
                                                        "gross": {
                                                            "type": "number",
                                                            "description": "Every settled payment in the window, in USD."
                                                        },
                                                        "fees": {
                                                            "type": "number",
                                                            "description": "The provider fees attributed to those payments, in USD."
                                                        },
                                                        "net": {
                                                            "type": "number",
                                                            "description": "`gross` minus `fees`."
                                                        },
                                                        "transactions": {
                                                            "type": "integer",
                                                            "description": "How many settled payments the window holds."
                                                        },
                                                        "currency": {
                                                            "type": "string",
                                                            "description": "Always `USD`: the figures are normalised."
                                                        }
                                                    },
                                                    "required": [
                                                        "gross",
                                                        "fees",
                                                        "net",
                                                        "transactions",
                                                        "currency"
                                                    ]
                                                },
                                                "timeseries": {
                                                    "type": "array",
                                                    "description": "One row per bucket, oldest first; empty buckets are omitted.",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "bucket": {
                                                                "type": "string",
                                                                "description": "The bucket's first day, `YYYY-MM-DD`."
                                                            },
                                                            "gross": {
                                                                "type": "number",
                                                                "description": "Settled payments in the bucket, in USD."
                                                            },
                                                            "fees": {
                                                                "type": "number",
                                                                "description": "Provider fees in the bucket, in USD."
                                                            },
                                                            "net": {
                                                                "type": "number",
                                                                "description": "`gross` minus `fees` for the bucket."
                                                            },
                                                            "transactions": {
                                                                "type": "integer",
                                                                "description": "Settled payments in the bucket."
                                                            }
                                                        },
                                                        "required": [
                                                            "bucket",
                                                            "gross",
                                                            "fees",
                                                            "net",
                                                            "transactions"
                                                        ]
                                                    }
                                                }
                                            },
                                            "required": [
                                                "range",
                                                "totals",
                                                "timeseries"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The request's window and scope, echoed back.",
                                            "properties": {
                                                "period": {
                                                    "type": "string",
                                                    "description": "The preset the window resolved from, as requested.",
                                                    "enum": [
                                                        "7d",
                                                        "14d",
                                                        "30d",
                                                        "60d",
                                                        "90d",
                                                        "1y",
                                                        "mtd",
                                                        "qtd",
                                                        "ytd",
                                                        "all"
                                                    ]
                                                },
                                                "granularity": {
                                                    "type": "string",
                                                    "description": "The bucket width, as requested."
                                                },
                                                "project_id": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The project the figures were scoped to, or `null` for every project the token may see."
                                                }
                                            },
                                            "required": [
                                                "period",
                                                "granularity",
                                                "project_id"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when `granularity` is not `day`, `week` or `month`, or `project_id` is not a UUID.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "dashboard:read"
                ],
                "x-mcp-tools": [
                    "get_earnings_report"
                ]
            }
        },
        "/v1/analytics/subscribers": {
            "get": {
                "operationId": "v1.analytics.subscribers",
                "description": "New sign-ups, cancellations, churn rate, trial-to-paid conversion and the status distribution of the window. The filter allow-lists do not apply: the figures describe the whole membership of the scope, which is what retention is measured against.\n\n```bash\ncurl \"https://api.subscriby.net/v1/analytics/subscribers?project_id=$PROJECT_ID\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```",
                "summary": "Subscriber analytics",
                "tags": [
                    "Analytics"
                ],
                "parameters": [
                    {
                        "name": "project_id",
                        "in": "query",
                        "description": "Scope the figures to one project the token may see; omit for every project visible to it. A project outside the token's `scope:project:` allow-list is `404 TENANT_MISMATCH`, an unknown one `404 RESOURCE_NOT_FOUND`.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "period",
                        "in": "query",
                        "description": "The preset window: `7d`, `14d`, `30d` (the default), `60d`, `90d`, `mtd`, `qtd`, `ytd`, `1y` or `all`. Ignored when both `from` and `to` are given; an unknown value falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "30d"
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "description": "The first day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "description": "The last day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "New, canceled, churn, trials and the status mix.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "range": {
                                                    "type": "object",
                                                    "description": "The window the preset resolved to.",
                                                    "properties": {
                                                        "from": {
                                                            "type": "string",
                                                            "description": "The first day of the window, `YYYY-MM-DD`.",
                                                            "examples": [
                                                                "2026-08-13"
                                                            ]
                                                        },
                                                        "to": {
                                                            "type": "string",
                                                            "description": "The last day of the window, `YYYY-MM-DD`.",
                                                            "examples": [
                                                                "2026-09-12"
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "from",
                                                        "to"
                                                    ]
                                                },
                                                "new_subscribers": {
                                                    "type": "integer",
                                                    "description": "Subscriptions created inside the window.",
                                                    "examples": [
                                                        54
                                                    ]
                                                },
                                                "canceled_subscribers": {
                                                    "type": "integer",
                                                    "description": "Subscriptions cancelled inside the window.",
                                                    "examples": [
                                                        6
                                                    ]
                                                },
                                                "active_at_window_start": {
                                                    "type": "integer",
                                                    "description": "Subscriptions that were active on the window's first day: the base the churn rate is measured against.",
                                                    "examples": [
                                                        241
                                                    ]
                                                },
                                                "churn_rate_percent": {
                                                    "type": "number",
                                                    "description": "`canceled_subscribers` as a percentage of `active_at_window_start`, two decimals; `0` when nobody was active.",
                                                    "examples": [
                                                        2.49
                                                    ]
                                                },
                                                "trial_started": {
                                                    "type": "integer",
                                                    "description": "Trials that began inside the window.",
                                                    "examples": [
                                                        38
                                                    ]
                                                },
                                                "trial_converted": {
                                                    "type": "integer",
                                                    "description": "Trials that became paying subscriptions inside the window.",
                                                    "examples": [
                                                        13
                                                    ]
                                                },
                                                "trial_to_paid_percent": {
                                                    "type": "number",
                                                    "description": "`trial_converted` as a percentage of `trial_started`, two decimals; `0` when no trial began.",
                                                    "examples": [
                                                        34.21
                                                    ]
                                                },
                                                "status_distribution": {
                                                    "type": "object",
                                                    "description": "How many subscriptions the scope holds in each payment status right now, keyed by status.",
                                                    "additionalProperties": {
                                                        "type": "integer",
                                                        "examples": [
                                                            289
                                                        ]
                                                    }
                                                }
                                            },
                                            "required": [
                                                "range",
                                                "new_subscribers",
                                                "canceled_subscribers",
                                                "active_at_window_start",
                                                "churn_rate_percent",
                                                "trial_started",
                                                "trial_converted",
                                                "trial_to_paid_percent",
                                                "status_distribution"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The request's window and scope, echoed back.",
                                            "properties": {
                                                "period": {
                                                    "type": "string",
                                                    "description": "The preset the window resolved from, as requested.",
                                                    "enum": [
                                                        "7d",
                                                        "14d",
                                                        "30d",
                                                        "60d",
                                                        "90d",
                                                        "1y",
                                                        "mtd",
                                                        "qtd",
                                                        "ytd",
                                                        "all"
                                                    ],
                                                    "examples": [
                                                        "30d"
                                                    ]
                                                },
                                                "project_id": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The project the figures were scoped to, or `null` for every project the token may see.",
                                                    "examples": [
                                                        "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "period",
                                                "project_id"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "range": {
                                                    "from": "2026-08-13",
                                                    "to": "2026-09-12"
                                                },
                                                "new_subscribers": 54,
                                                "canceled_subscribers": 6,
                                                "active_at_window_start": 241,
                                                "churn_rate_percent": 2.49,
                                                "trial_started": 38,
                                                "trial_converted": 13,
                                                "trial_to_paid_percent": 34.21,
                                                "status_distribution": {
                                                    "active": 289,
                                                    "trial": 25,
                                                    "past_due": 3,
                                                    "canceled": 41,
                                                    "expired": 118
                                                }
                                            },
                                            "meta": {
                                                "period": "30d",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when `project_id` is not a UUID.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "dashboard:read"
                ],
                "x-mcp-tools": [
                    "get_subscriber_analytics"
                ]
            }
        },
        "/v1/analytics/transactions": {
            "get": {
                "operationId": "v1.analytics.transactions",
                "description": "A keyset-paginated list of payments for one project. `project_id` is **required**.\n\n```bash\ncurl \"https://api.subscriby.net/v1/analytics/transactions?project_id=$PROJECT_ID&limit=100\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nEvery row carries its owning project, plan and subscriber, so a payment can be attributed without a follow-up lookup. Follow `meta.next_cursor` on the next call to paginate. A `null` or missing cursor means the end of the range has been reached.",
                "summary": "List transactions",
                "tags": [
                    "Analytics"
                ],
                "parameters": [
                    {
                        "name": "project_id",
                        "in": "query",
                        "required": true,
                        "description": "The project whose payments to list. Required: transactions are always read for one project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "period",
                        "in": "query",
                        "description": "The preset window: `7d`, `14d`, `30d` (the default), `60d`, `90d`, `mtd`, `qtd`, `ytd`, `1y` or `all`. Ignored when both `from` and `to` are given; an unknown value falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "30d"
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "description": "The first day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "description": "The last day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "statuses[]",
                        "in": "query",
                        "description": "Only payments in these states: `successful`, `failed`, `pending`, `refunded`. Send them as `statuses[]=a&statuses[]=b` or as one comma-separated string; an unknown state is ignored.",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    },
                    {
                        "name": "provider_ids[]",
                        "in": "query",
                        "description": "Only payments taken through these payment methods. Send them as `provider_ids[]=a&provider_ids[]=b` or as one comma-separated string.",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    },
                    {
                        "name": "plan_ids[]",
                        "in": "query",
                        "description": "Count only these plans. Send it as `plan_ids[]=a&plan_ids[]=b` or as one comma-separated string.",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    },
                    {
                        "name": "currency_ids[]",
                        "in": "query",
                        "description": "Only payments in these currencies, by currency id. Send them as `currency_ids[]=a&currency_ids[]=b` or as one comma-separated string.",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "description": "The opaque keyset cursor a previous page returned as `meta.next_cursor`. Omit for the first page.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Rows per page, 1 to 200; a value outside the range clamps. Defaults to 50.",
                        "schema": {
                            "type": "integer",
                            "default": 50
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "One keyset page of transactions.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "The payment's id.",
                                                        "examples": [
                                                            "8b0c4a15-e792-4360-95d8-1f47c0b3e926"
                                                        ]
                                                    },
                                                    "subscription_id": {
                                                        "type": "string",
                                                        "description": "The subscription the payment belongs to.",
                                                        "examples": [
                                                            "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                                                        ]
                                                    },
                                                    "project_id": {
                                                        "type": "string",
                                                        "description": "The owning project.",
                                                        "examples": [
                                                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                                        ]
                                                    },
                                                    "project_name": {
                                                        "type": "string",
                                                        "description": "The owning project's name.",
                                                        "examples": [
                                                            "Beautiful Mouths"
                                                        ]
                                                    },
                                                    "plan_id": {
                                                        "type": "string",
                                                        "description": "The plan the subscription is on.",
                                                        "examples": [
                                                            "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b"
                                                        ]
                                                    },
                                                    "plan_name": {
                                                        "type": "string",
                                                        "description": "That plan's name.",
                                                        "examples": [
                                                            "Monthly"
                                                        ]
                                                    },
                                                    "subscriber_id": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "The member; `null` while the subscription has not been claimed by a member yet.",
                                                        "examples": [
                                                            "6f9b2e37-c184-4a05-8d72-30e16bc9f458"
                                                        ]
                                                    },
                                                    "subscriber_name": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "The member's display name; `null` while the subscription has not been claimed.",
                                                        "examples": [
                                                            "Ada Lovelace"
                                                        ]
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "`successful`, `failed`, `pending` or `refunded`.",
                                                        "enum": [
                                                            "successful",
                                                            "failed",
                                                            "pending",
                                                            "refunded"
                                                        ],
                                                        "examples": [
                                                            "successful"
                                                        ]
                                                    },
                                                    "amount": {
                                                        "type": "string",
                                                        "description": "The charged amount as a decimal string, in `currency`.",
                                                        "examples": [
                                                            "29.00"
                                                        ]
                                                    },
                                                    "currency": {
                                                        "type": "string",
                                                        "description": "The charge's ISO 4217 currency code.",
                                                        "examples": [
                                                            "USD"
                                                        ]
                                                    },
                                                    "provider": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "The payment provider's key.",
                                                        "enum": [
                                                            "stripe",
                                                            "paypal",
                                                            "skrill",
                                                            "coinpayments",
                                                            "paystack",
                                                            "razorpay",
                                                            "ceypay",
                                                            "platformcurrency",
                                                            "accesscode",
                                                            null
                                                        ],
                                                        "examples": [
                                                            "stripe"
                                                        ]
                                                    },
                                                    "provider_label": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "The payment provider's display name.",
                                                        "enum": [
                                                            "Stripe",
                                                            "PayPal",
                                                            "Skrill",
                                                            "CoinPayments",
                                                            "Paystack",
                                                            "Razorpay",
                                                            "CeyPay",
                                                            "Platform Currency",
                                                            "Access Codes",
                                                            null
                                                        ],
                                                        "examples": [
                                                            "Stripe"
                                                        ]
                                                    },
                                                    "method_id": {
                                                        "type": "string",
                                                        "description": "The project payment method the charge went through.",
                                                        "examples": [
                                                            "a15d70c8-3e46-4b92-b70f-58c9d2140e63"
                                                        ]
                                                    },
                                                    "calculated_fee": {
                                                        "type": "string",
                                                        "description": "The provider fee attributed to the payment, as a decimal string.",
                                                        "examples": [
                                                            "1.16"
                                                        ]
                                                    },
                                                    "billing_reason": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Why the charge happened, such as `subscription_cycle` for a renewal.",
                                                        "examples": [
                                                            "subscription_cycle"
                                                        ]
                                                    },
                                                    "external_payment_id": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "The provider's own id for the charge.",
                                                        "examples": [
                                                            "pi_3Nxy..."
                                                        ]
                                                    },
                                                    "occurred_at": {
                                                        "type": "string",
                                                        "description": "When the payment settled, ISO 8601.",
                                                        "examples": [
                                                            "2026-05-18T10:05:00Z"
                                                        ]
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "subscription_id",
                                                    "project_id",
                                                    "project_name",
                                                    "plan_id",
                                                    "plan_name",
                                                    "subscriber_id",
                                                    "subscriber_name",
                                                    "status",
                                                    "amount",
                                                    "currency",
                                                    "provider",
                                                    "provider_label",
                                                    "method_id",
                                                    "calculated_fee",
                                                    "billing_reason",
                                                    "external_payment_id",
                                                    "occurred_at"
                                                ]
                                            }
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The page's cursor and the window and project it was cut from.",
                                            "properties": {
                                                "count": {
                                                    "type": "integer",
                                                    "description": "How many rows this page holds.",
                                                    "examples": [
                                                        1
                                                    ]
                                                },
                                                "limit": {
                                                    "type": "integer",
                                                    "description": "The page size that was applied.",
                                                    "examples": [
                                                        100
                                                    ]
                                                },
                                                "next_cursor": {
                                                    "type": "string",
                                                    "description": "The opaque cursor for the next page; `null` when this page is the last.",
                                                    "examples": [
                                                        "eyJpZCI6InR4bl8uLi4i..."
                                                    ]
                                                },
                                                "range": {
                                                    "type": "object",
                                                    "description": "The window the preset resolved to.",
                                                    "properties": {
                                                        "from": {
                                                            "type": "string",
                                                            "description": "The first day of the window, `YYYY-MM-DD`.",
                                                            "examples": [
                                                                "2026-08-13"
                                                            ]
                                                        },
                                                        "to": {
                                                            "type": "string",
                                                            "description": "The last day of the window, `YYYY-MM-DD`.",
                                                            "examples": [
                                                                "2026-09-12"
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "from",
                                                        "to"
                                                    ]
                                                },
                                                "project_id": {
                                                    "type": "string",
                                                    "description": "The project the rows belong to, as requested.",
                                                    "examples": [
                                                        "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "count",
                                                "limit",
                                                "next_cursor",
                                                "range",
                                                "project_id"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "8b0c4a15-e792-4360-95d8-1f47c0b3e926",
                                                    "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                    "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                    "project_name": "Beautiful Mouths",
                                                    "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                    "plan_name": "Monthly",
                                                    "subscriber_id": "6f9b2e37-c184-4a05-8d72-30e16bc9f458",
                                                    "subscriber_name": "Ada Lovelace",
                                                    "status": "successful",
                                                    "amount": "29.00",
                                                    "currency": "USD",
                                                    "provider": "stripe",
                                                    "provider_label": "Stripe",
                                                    "method_id": "a15d70c8-3e46-4b92-b70f-58c9d2140e63",
                                                    "calculated_fee": "1.16",
                                                    "billing_reason": "subscription_cycle",
                                                    "external_payment_id": "pi_3Nxy...",
                                                    "occurred_at": "2026-05-18T10:05:00Z"
                                                }
                                            ],
                                            "meta": {
                                                "count": 1,
                                                "limit": 100,
                                                "next_cursor": "eyJpZCI6InR4bl8uLi4i...",
                                                "range": {
                                                    "from": "2026-08-13",
                                                    "to": "2026-09-12"
                                                },
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when `project_id` is missing or not a UUID.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "dashboard:read"
                ],
                "x-mcp-tools": [
                    "list_transactions"
                ]
            }
        },
        "/v1/analytics/transactions/breakdown": {
            "get": {
                "operationId": "v1.analytics.transactions.breakdown",
                "description": "USD-normalised successful-payment totals grouped by one `dimension`: `plan`, `payment_provider`, `currency` or `project`. `dimension` is **required**.\n\n```bash\ncurl \"https://api.subscriby.net/v1/analytics/transactions/breakdown?dimension=payment_provider&period=90d\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```",
                "summary": "Transaction breakdown",
                "tags": [
                    "Analytics"
                ],
                "parameters": [
                    {
                        "name": "dimension",
                        "in": "query",
                        "required": true,
                        "description": "What to group the settled revenue by: `plan`, `payment_provider`, `currency` or `project`. Required.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "payment_provider"
                    },
                    {
                        "name": "project_id",
                        "in": "query",
                        "description": "Scope the figures to one project the token may see; omit for every project visible to it. A project outside the token's `scope:project:` allow-list is `404 TENANT_MISMATCH`, an unknown one `404 RESOURCE_NOT_FOUND`.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "period",
                        "in": "query",
                        "description": "The preset window: `7d`, `14d`, `30d` (the default), `60d`, `90d`, `mtd`, `qtd`, `ytd`, `1y` or `all`. Ignored when both `from` and `to` are given; an unknown value falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "30d"
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "description": "The first day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "description": "The last day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "plan_ids[]",
                        "in": "query",
                        "description": "Count only these plans. Send it as `plan_ids[]=a&plan_ids[]=b` or as one comma-separated string.",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    },
                    {
                        "name": "statuses[]",
                        "in": "query",
                        "description": "Count only payments in these states: `successful`, `failed`, `pending`, `refunded`. Send them as `statuses[]=a&statuses[]=b` or as one comma-separated string.",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    },
                    {
                        "name": "payment_method_ids[]",
                        "in": "query",
                        "description": "Count only payments taken through these payment methods. Send them as `payment_method_ids[]=a&payment_method_ids[]=b` or as one comma-separated string.",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Gross revenue grouped by the dimension.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "range": {
                                                    "type": "object",
                                                    "description": "The window the preset resolved to.",
                                                    "properties": {
                                                        "from": {
                                                            "type": "string",
                                                            "description": "The first day of the window, `YYYY-MM-DD`.",
                                                            "examples": [
                                                                "2026-06-14"
                                                            ]
                                                        },
                                                        "to": {
                                                            "type": "string",
                                                            "description": "The last day of the window, `YYYY-MM-DD`.",
                                                            "examples": [
                                                                "2026-09-12"
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "from",
                                                        "to"
                                                    ]
                                                },
                                                "dimension": {
                                                    "type": "string",
                                                    "description": "The dimension the payments were grouped by: `plan`, `payment_provider`, `currency` or `project`.",
                                                    "examples": [
                                                        "payment_provider"
                                                    ]
                                                },
                                                "total_gross_usd": {
                                                    "type": "number",
                                                    "description": "Every settled payment in the window, in USD; the base `share_percent` is measured against.",
                                                    "examples": [
                                                        4210.5
                                                    ]
                                                },
                                                "groups": {
                                                    "type": "array",
                                                    "description": "One row per distinct value of the dimension, largest gross first.",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "key": {
                                                                "type": "string",
                                                                "description": "The value's identifier: a plan or project id, a provider key or a currency code.",
                                                                "examples": [
                                                                    "stripe"
                                                                ]
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The value's display name, in the creator's language where it has one.",
                                                                "examples": [
                                                                    "Stripe"
                                                                ]
                                                            },
                                                            "gross_usd": {
                                                                "type": "number",
                                                                "description": "The group's settled payments in the window, converted to USD.",
                                                                "examples": [
                                                                    3120
                                                                ]
                                                            },
                                                            "transactions": {
                                                                "type": "integer",
                                                                "description": "How many settled payments the group holds.",
                                                                "examples": [
                                                                    104
                                                                ]
                                                            },
                                                            "share_percent": {
                                                                "type": "number",
                                                                "description": "The group's part of `total_gross_usd`, two decimals.",
                                                                "examples": [
                                                                    74.1
                                                                ]
                                                            }
                                                        },
                                                        "required": [
                                                            "key",
                                                            "label",
                                                            "gross_usd",
                                                            "transactions",
                                                            "share_percent"
                                                        ]
                                                    }
                                                }
                                            },
                                            "required": [
                                                "range",
                                                "dimension",
                                                "total_gross_usd",
                                                "groups"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The request's window, dimension and scope, echoed back.",
                                            "properties": {
                                                "period": {
                                                    "type": "string",
                                                    "description": "The preset the window resolved from, as requested.",
                                                    "enum": [
                                                        "7d",
                                                        "14d",
                                                        "30d",
                                                        "60d",
                                                        "90d",
                                                        "1y",
                                                        "mtd",
                                                        "qtd",
                                                        "ytd",
                                                        "all"
                                                    ],
                                                    "examples": [
                                                        "90d"
                                                    ]
                                                },
                                                "dimension": {
                                                    "type": "string",
                                                    "description": "The dimension, as requested.",
                                                    "examples": [
                                                        "payment_provider"
                                                    ]
                                                },
                                                "project_id": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The project the figures were scoped to, or `null` for every project the token may see.",
                                                    "examples": [
                                                        null
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "period",
                                                "dimension",
                                                "project_id"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "range": {
                                                    "from": "2026-06-14",
                                                    "to": "2026-09-12"
                                                },
                                                "dimension": "payment_provider",
                                                "total_gross_usd": 4210.5,
                                                "groups": [
                                                    {
                                                        "key": "stripe",
                                                        "label": "Stripe",
                                                        "gross_usd": 3120,
                                                        "transactions": 104,
                                                        "share_percent": 74.1
                                                    },
                                                    {
                                                        "key": "paypal",
                                                        "label": "PayPal",
                                                        "gross_usd": 1090.5,
                                                        "transactions": 37,
                                                        "share_percent": 25.9
                                                    }
                                                ]
                                            },
                                            "meta": {
                                                "period": "90d",
                                                "dimension": "payment_provider",
                                                "project_id": null
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when `dimension` is missing or not one of the four, or `project_id` is not a UUID.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "dashboard:read"
                ],
                "x-mcp-tools": [
                    "get_transaction_breakdown"
                ]
            }
        },
        "/v1/analytics/plan-performance": {
            "get": {
                "operationId": "v1.analytics.plan-performance",
                "description": "A per-plan breakdown for one project: active subscribers, revenue in the window, payments in the window and the average ticket. `project_id` is **required**.\n\n```bash\ncurl \"https://api.subscriby.net/v1/analytics/plan-performance?project_id=$PROJECT_ID&period=30d\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nFigures are in the plan's own currency. `meta.range` is the window the preset resolved to.",
                "summary": "Plan performance",
                "tags": [
                    "Analytics"
                ],
                "parameters": [
                    {
                        "name": "project_id",
                        "in": "query",
                        "required": true,
                        "description": "The project whose plans to report on. Required: the figures are per plan of one project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "period",
                        "in": "query",
                        "description": "The preset window: `7d`, `14d`, `30d` (the default), `60d`, `90d`, `mtd`, `qtd`, `ytd`, `1y` or `all`. Ignored when both `from` and `to` are given; an unknown value falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "30d"
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "description": "The first day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "description": "The last day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Per-plan activity in the plan's own currency.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "plan_id": {
                                                        "type": "string",
                                                        "description": "The plan.",
                                                        "examples": [
                                                            "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b"
                                                        ]
                                                    },
                                                    "plan_name": {
                                                        "type": "string",
                                                        "description": "The plan's name.",
                                                        "examples": [
                                                            "Premium Monthly"
                                                        ]
                                                    },
                                                    "active_subscribers": {
                                                        "type": "integer",
                                                        "description": "Subscriptions on the plan that are active right now.",
                                                        "examples": [
                                                            241
                                                        ],
                                                        "minimum": 0
                                                    },
                                                    "payments_in_window": {
                                                        "type": "integer",
                                                        "description": "Settled payments on the plan inside the window.",
                                                        "examples": [
                                                            58
                                                        ],
                                                        "minimum": 0
                                                    },
                                                    "revenue_in_window": {
                                                        "type": "string",
                                                        "description": "Those payments summed, as a decimal string in the plan's own currency.",
                                                        "examples": [
                                                            "1682.00"
                                                        ]
                                                    },
                                                    "avg_ticket": {
                                                        "type": "string",
                                                        "description": "`revenue_in_window` divided by `payments_in_window`, as a decimal string.",
                                                        "examples": [
                                                            "29.00"
                                                        ]
                                                    }
                                                },
                                                "required": [
                                                    "plan_id",
                                                    "plan_name",
                                                    "active_subscribers",
                                                    "payments_in_window",
                                                    "revenue_in_window",
                                                    "avg_ticket"
                                                ]
                                            }
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The request's project and window, echoed back.",
                                            "properties": {
                                                "project_id": {
                                                    "type": "string",
                                                    "description": "The project, as requested.",
                                                    "examples": [
                                                        "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                                    ]
                                                },
                                                "period": {
                                                    "type": "string",
                                                    "description": "The preset the window resolved from, as requested.",
                                                    "enum": [
                                                        "7d",
                                                        "14d",
                                                        "30d",
                                                        "60d",
                                                        "90d",
                                                        "1y",
                                                        "mtd",
                                                        "qtd",
                                                        "ytd",
                                                        "all"
                                                    ],
                                                    "examples": [
                                                        "30d"
                                                    ]
                                                },
                                                "range": {
                                                    "type": "object",
                                                    "description": "The window the preset resolved to.",
                                                    "properties": {
                                                        "from": {
                                                            "type": "string",
                                                            "description": "The first day of the window, `YYYY-MM-DD`.",
                                                            "examples": [
                                                                "2026-04-18"
                                                            ]
                                                        },
                                                        "to": {
                                                            "type": "string",
                                                            "description": "The last day of the window, `YYYY-MM-DD`.",
                                                            "examples": [
                                                                "2026-05-18"
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "from",
                                                        "to"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "project_id",
                                                "period",
                                                "range"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                    "plan_name": "Premium Monthly",
                                                    "active_subscribers": 241,
                                                    "payments_in_window": 58,
                                                    "revenue_in_window": "1682.00",
                                                    "avg_ticket": "29.00"
                                                }
                                            ],
                                            "meta": {
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "period": "30d",
                                                "range": {
                                                    "from": "2026-04-18",
                                                    "to": "2026-05-18"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when `project_id` is missing or not a UUID.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "dashboard:read"
                ],
                "x-mcp-tools": [
                    "get_plan_performance"
                ]
            }
        },
        "/v1/analytics/connectors": {
            "get": {
                "operationId": "v1.analytics.connectors",
                "description": "Members, access and revenue per connector: one row for every connector the scope's projects run or ever granted access on. The figures behind the dashboards' **By Connector** panel.\n\n```bash\ncurl \"https://api.subscriby.net/v1/analytics/connectors?project_id=$PROJECT_ID&period=30d\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\n- `installations` counts the live, not uninstalled, installations of the connector in the scope; `members` the members holding at least one account linked on it; `members_linked_in_window` those who linked one inside the window.\n- `live_grants` and `pending_grants` read the access ledger now (pending covers `pending`, `pending_identity` and `held`); `granted_in_window` and `revoked_in_window` count the ledger's moves inside the window.\n- `gross_usd` is every settled payment in the window whose purchase granted access on the connector, converted to USD; `share_percent` is its part of `total_gross_usd`. A purchase that grants access on two connectors counts toward both, so shares can exceed 100 in total; `attribution` says so in the creator's language.\n- The filter allow-lists (`plan_ids`, `statuses`, `payment_method_ids`) do not apply here: installations and linked accounts are not subscriptions.",
                "summary": "By connector",
                "tags": [
                    "Analytics"
                ],
                "parameters": [
                    {
                        "name": "project_id",
                        "in": "query",
                        "description": "Scope the figures to one project the token may see; omit for every project visible to it. A project outside the token's `scope:project:` allow-list is `404 TENANT_MISMATCH`, an unknown one `404 RESOURCE_NOT_FOUND`.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "period",
                        "in": "query",
                        "description": "The preset window: `7d`, `14d`, `30d` (the default), `60d`, `90d`, `mtd`, `qtd`, `ytd`, `1y` or `all`. Ignored when both `from` and `to` are given; an unknown value falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "30d"
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "description": "The first day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "description": "The last day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "One row per connector: installations, members, grants, revenue and share.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "range": {
                                                    "type": "object",
                                                    "description": "The window the preset resolved to.",
                                                    "properties": {
                                                        "from": {
                                                            "type": "string",
                                                            "description": "The first day of the window, `YYYY-MM-DD`.",
                                                            "examples": [
                                                                "2026-08-13"
                                                            ]
                                                        },
                                                        "to": {
                                                            "type": "string",
                                                            "description": "The last day of the window, `YYYY-MM-DD`.",
                                                            "examples": [
                                                                "2026-09-12"
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "from",
                                                        "to"
                                                    ]
                                                },
                                                "total_gross_usd": {
                                                    "type": "number",
                                                    "description": "Every settled payment in the window, in USD; the base `share_percent` is measured against.",
                                                    "examples": [
                                                        1682
                                                    ]
                                                },
                                                "attribution": {
                                                    "type": "string",
                                                    "description": "One sentence, in the creator's language, saying that a purchase granting access on two connectors counts toward both.",
                                                    "const": "A purchase that grants access on two connectors counts toward both.",
                                                    "examples": [
                                                        "A purchase that grants access on two connectors counts toward both."
                                                    ]
                                                },
                                                "connectors": {
                                                    "type": "array",
                                                    "description": "One row per connector the scope's projects run or ever granted access on.",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "key": {
                                                                "type": "string",
                                                                "description": "The connector's key.",
                                                                "examples": [
                                                                    "example"
                                                                ]
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "The connector's display name.",
                                                                "examples": [
                                                                    "Example connector"
                                                                ]
                                                            },
                                                            "installations": {
                                                                "type": "integer",
                                                                "description": "Live, not uninstalled, installations of the connector in the scope.",
                                                                "examples": [
                                                                    2
                                                                ]
                                                            },
                                                            "members": {
                                                                "type": "integer",
                                                                "description": "Members holding at least one account linked on the connector.",
                                                                "examples": [
                                                                    241
                                                                ]
                                                            },
                                                            "members_linked_in_window": {
                                                                "type": "integer",
                                                                "description": "Members who linked an account on it inside the window.",
                                                                "examples": [
                                                                    18
                                                                ]
                                                            },
                                                            "live_grants": {
                                                                "type": "integer",
                                                                "description": "Access ledger rows on the connector that are granted right now.",
                                                                "examples": [
                                                                    236
                                                                ]
                                                            },
                                                            "pending_grants": {
                                                                "type": "integer",
                                                                "description": "Ledger rows waiting to be issued: `pending`, `pending_identity` or `held`.",
                                                                "examples": [
                                                                    3
                                                                ]
                                                            },
                                                            "granted_in_window": {
                                                                "type": "integer",
                                                                "description": "Ledger rows that became granted inside the window.",
                                                                "examples": [
                                                                    21
                                                                ]
                                                            },
                                                            "revoked_in_window": {
                                                                "type": "integer",
                                                                "description": "Ledger rows that were revoked inside the window.",
                                                                "examples": [
                                                                    4
                                                                ]
                                                            },
                                                            "gross_usd": {
                                                                "type": "number",
                                                                "description": "Settled payments in the window whose purchase granted access on the connector, converted to USD.",
                                                                "examples": [
                                                                    1682
                                                                ]
                                                            },
                                                            "transactions": {
                                                                "description": "How many such payments there were.",
                                                                "anyOf": [
                                                                    {
                                                                        "type": "string"
                                                                    },
                                                                    {
                                                                        "type": "integer",
                                                                        "enum": [
                                                                            0
                                                                        ],
                                                                        "examples": [
                                                                            58
                                                                        ]
                                                                    }
                                                                ]
                                                            },
                                                            "share_percent": {
                                                                "type": "number",
                                                                "description": "`gross_usd` as a part of `total_gross_usd`; the shares can exceed 100 in total.",
                                                                "examples": [
                                                                    100
                                                                ]
                                                            }
                                                        },
                                                        "required": [
                                                            "key",
                                                            "name",
                                                            "installations",
                                                            "members",
                                                            "members_linked_in_window",
                                                            "live_grants",
                                                            "pending_grants",
                                                            "granted_in_window",
                                                            "revoked_in_window",
                                                            "gross_usd",
                                                            "transactions",
                                                            "share_percent"
                                                        ]
                                                    }
                                                }
                                            },
                                            "required": [
                                                "range",
                                                "total_gross_usd",
                                                "attribution",
                                                "connectors"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The request's window and scope, echoed back.",
                                            "properties": {
                                                "period": {
                                                    "type": "string",
                                                    "description": "The preset the window resolved from, as requested.",
                                                    "enum": [
                                                        "7d",
                                                        "14d",
                                                        "30d",
                                                        "60d",
                                                        "90d",
                                                        "1y",
                                                        "mtd",
                                                        "qtd",
                                                        "ytd",
                                                        "all"
                                                    ],
                                                    "examples": [
                                                        "30d"
                                                    ]
                                                },
                                                "project_id": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The project the figures were scoped to, or `null` for every project the token may see.",
                                                    "examples": [
                                                        "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "period",
                                                "project_id"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "range": {
                                                    "from": "2026-08-13",
                                                    "to": "2026-09-12"
                                                },
                                                "total_gross_usd": 1682,
                                                "attribution": "A purchase that grants access on two connectors counts toward both.",
                                                "connectors": [
                                                    {
                                                        "key": "example",
                                                        "name": "Example connector",
                                                        "installations": 2,
                                                        "members": 241,
                                                        "members_linked_in_window": 18,
                                                        "live_grants": 236,
                                                        "pending_grants": 3,
                                                        "granted_in_window": 21,
                                                        "revoked_in_window": 4,
                                                        "gross_usd": 1682,
                                                        "transactions": 58,
                                                        "share_percent": 100
                                                    }
                                                ]
                                            },
                                            "meta": {
                                                "period": "30d",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "dashboard:read"
                ],
                "x-mcp-tools": [
                    "get_connector_analytics"
                ]
            }
        },
        "/v1/analytics/composition": {
            "get": {
                "operationId": "v1.analytics.composition",
                "description": "How the window's revenue and payments are composed, as the five donuts the dashboards draw: transaction fees by payment provider, settled transactions by plan kind, gross revenue by currency, payment attempts by outcome, and the monthly recurring revenue split by plan.\n\n```bash\ncurl \"https://api.subscriby.net/v1/analytics/composition?project_id=$PROJECT_ID&period=30d\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\n- Every dataset carries `total`, `unit` (`usd` or `count`) and `slices` sorted largest first; each slice has its `key`, `label`, `value`, `share_percent` and the `color` the dashboard draws it in, so a client can render the same donut.\n- `fees_by_provider`, `transactions_by_kind` and `revenue_by_currency` read the same settled payments, so they agree with each other to the cent; `payment_outcomes` reads every attempt in the window, because a failed charge is exactly what it exists to show.\n- `mrr_by_plan` ignores the window: MRR is a balance, not a flow. It counts every active subscription on a recurring plan, normalised to a monthly USD figure, filed under its plan.\n- Labels come back in the creator's language.",
                "summary": "Revenue composition",
                "tags": [
                    "Analytics"
                ],
                "parameters": [
                    {
                        "name": "project_id",
                        "in": "query",
                        "description": "Scope the figures to one project the token may see; omit for every project visible to it. A project outside the token's `scope:project:` allow-list is `404 TENANT_MISMATCH`, an unknown one `404 RESOURCE_NOT_FOUND`.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "period",
                        "in": "query",
                        "description": "The preset window: `7d`, `14d`, `30d` (the default), `60d`, `90d`, `mtd`, `qtd`, `ytd`, `1y` or `all`. Ignored when both `from` and `to` are given; an unknown value falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "30d"
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "description": "The first day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "description": "The last day of an explicit window, `YYYY-MM-DD`. Both `from` and `to` are needed to override `period`.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The four dashboard donuts for the window plus the MRR base split by plan, each as `total`, `unit` and `slices`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "range": {
                                                    "type": "object",
                                                    "description": "The window the preset resolved to.",
                                                    "properties": {
                                                        "from": {
                                                            "type": "string",
                                                            "description": "The first day of the window, `YYYY-MM-DD`.",
                                                            "examples": [
                                                                "2026-08-13"
                                                            ]
                                                        },
                                                        "to": {
                                                            "type": "string",
                                                            "description": "The last day of the window, `YYYY-MM-DD`.",
                                                            "examples": [
                                                                "2026-09-12"
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "from",
                                                        "to"
                                                    ]
                                                },
                                                "fees_by_provider": {
                                                    "type": "object",
                                                    "description": "Provider fees on the window's settled payments, split by payment provider, in USD.",
                                                    "additionalProperties": {
                                                        "examples": [
                                                            84.1
                                                        ]
                                                    }
                                                },
                                                "transactions_by_kind": {
                                                    "type": "object",
                                                    "description": "The window's settled payments counted by the kind of plan they bought.",
                                                    "additionalProperties": {
                                                        "examples": [
                                                            58
                                                        ]
                                                    }
                                                },
                                                "revenue_by_currency": {
                                                    "type": "object",
                                                    "description": "The window's settled payments summed by the currency they were charged in, each converted to USD.",
                                                    "additionalProperties": {
                                                        "examples": [
                                                            1682
                                                        ]
                                                    }
                                                },
                                                "payment_outcomes": {
                                                    "type": "object",
                                                    "description": "Every payment attempt in the window counted by outcome, including the failed ones.",
                                                    "additionalProperties": {
                                                        "examples": [
                                                            63
                                                        ]
                                                    }
                                                },
                                                "mrr_by_plan": {
                                                    "type": "object",
                                                    "description": "The monthly recurring revenue of every active subscription on a recurring plan, split by plan, in USD; independent of the window.",
                                                    "properties": {
                                                        "total": {
                                                            "type": "number",
                                                            "description": "The MRR summed.",
                                                            "examples": [
                                                                4120
                                                            ]
                                                        },
                                                        "unit": {
                                                            "type": "string",
                                                            "description": "Always `usd`.",
                                                            "examples": [
                                                                "usd"
                                                            ]
                                                        },
                                                        "slices": {
                                                            "type": "array",
                                                            "description": "One slice per recurring plan with active subscriptions, largest first.",
                                                            "items": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "key": {
                                                                        "type": "string",
                                                                        "description": "The plan's id.",
                                                                        "examples": [
                                                                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                                                        ]
                                                                    },
                                                                    "label": {
                                                                        "type": "string",
                                                                        "description": "The plan's name.",
                                                                        "examples": [
                                                                            "Gold"
                                                                        ]
                                                                    },
                                                                    "value": {
                                                                        "type": "number",
                                                                        "description": "The plan's MRR in USD.",
                                                                        "examples": [
                                                                            2980
                                                                        ]
                                                                    },
                                                                    "share_percent": {
                                                                        "type": "number",
                                                                        "description": "The slice's part of `total`, one decimal.",
                                                                        "examples": [
                                                                            72.33
                                                                        ]
                                                                    },
                                                                    "color": {
                                                                        "type": "string",
                                                                        "description": "The colour the dashboard draws the slice in.",
                                                                        "examples": [
                                                                            "blue"
                                                                        ]
                                                                    }
                                                                },
                                                                "required": [
                                                                    "key",
                                                                    "label",
                                                                    "value",
                                                                    "share_percent",
                                                                    "color"
                                                                ]
                                                            }
                                                        }
                                                    },
                                                    "required": [
                                                        "total",
                                                        "unit",
                                                        "slices"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "range",
                                                "fees_by_provider",
                                                "transactions_by_kind",
                                                "revenue_by_currency",
                                                "payment_outcomes",
                                                "mrr_by_plan"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The request's window and scope, echoed back.",
                                            "properties": {
                                                "period": {
                                                    "type": "string",
                                                    "description": "The preset the window resolved from, as requested.",
                                                    "enum": [
                                                        "7d",
                                                        "14d",
                                                        "30d",
                                                        "60d",
                                                        "90d",
                                                        "1y",
                                                        "mtd",
                                                        "qtd",
                                                        "ytd",
                                                        "all"
                                                    ],
                                                    "examples": [
                                                        "30d"
                                                    ]
                                                },
                                                "project_id": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The project the figures were scoped to, or `null` for every project the token may see.",
                                                    "examples": [
                                                        "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "period",
                                                "project_id"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "range": {
                                                    "from": "2026-08-13",
                                                    "to": "2026-09-12"
                                                },
                                                "fees_by_provider": {
                                                    "total": 84.1,
                                                    "unit": "usd",
                                                    "slices": [
                                                        {
                                                            "key": "stripe",
                                                            "label": "Stripe",
                                                            "value": 61.4,
                                                            "share_percent": 73.01,
                                                            "color": "blue"
                                                        },
                                                        {
                                                            "key": "paypal",
                                                            "label": "PayPal",
                                                            "value": 22.7,
                                                            "share_percent": 26.99,
                                                            "color": "violet"
                                                        }
                                                    ]
                                                },
                                                "transactions_by_kind": {
                                                    "total": 58,
                                                    "unit": "count",
                                                    "slices": [
                                                        {
                                                            "key": "subscription",
                                                            "label": "Subscription",
                                                            "value": 41,
                                                            "share_percent": 70.69,
                                                            "color": "blue"
                                                        },
                                                        {
                                                            "key": "pass",
                                                            "label": "Pass",
                                                            "value": 17,
                                                            "share_percent": 29.31,
                                                            "color": "violet"
                                                        }
                                                    ]
                                                },
                                                "revenue_by_currency": {
                                                    "total": 1682,
                                                    "unit": "usd",
                                                    "slices": [
                                                        {
                                                            "key": "USD",
                                                            "label": "USD",
                                                            "value": 1490,
                                                            "share_percent": 88.59,
                                                            "color": "blue"
                                                        },
                                                        {
                                                            "key": "EUR",
                                                            "label": "EUR",
                                                            "value": 192,
                                                            "share_percent": 11.41,
                                                            "color": "violet"
                                                        }
                                                    ]
                                                },
                                                "payment_outcomes": {
                                                    "total": 63,
                                                    "unit": "count",
                                                    "slices": [
                                                        {
                                                            "key": "succeeded",
                                                            "label": "Succeeded",
                                                            "value": 58,
                                                            "share_percent": 92.06,
                                                            "color": "emerald"
                                                        },
                                                        {
                                                            "key": "failed",
                                                            "label": "Failed",
                                                            "value": 4,
                                                            "share_percent": 6.35,
                                                            "color": "rose"
                                                        },
                                                        {
                                                            "key": "pending",
                                                            "label": "Pending",
                                                            "value": 1,
                                                            "share_percent": 1.59,
                                                            "color": "amber"
                                                        }
                                                    ]
                                                },
                                                "mrr_by_plan": {
                                                    "total": 4120,
                                                    "unit": "usd",
                                                    "slices": [
                                                        {
                                                            "key": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                            "label": "Gold",
                                                            "value": 2980,
                                                            "share_percent": 72.33,
                                                            "color": "blue"
                                                        },
                                                        {
                                                            "key": "0c1e7a54-2f6b-4d8e-9a3c-1b5d7e9f2a46",
                                                            "label": "Silver",
                                                            "value": 1140,
                                                            "share_percent": 27.67,
                                                            "color": "violet"
                                                        }
                                                    ]
                                                }
                                            },
                                            "meta": {
                                                "period": "30d",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "dashboard:read"
                ],
                "x-mcp-tools": [
                    "get_revenue_composition"
                ]
            }
        },
        "/v1/projects/{project}/broadcasts/audiences": {
            "get": {
                "operationId": "v1.broadcasts.audiences",
                "description": "All thirteen segments with labels, descriptions and current counts, so a UI can offer them without hard-coding the list. Segments that address a single window report `recipient_estimate: null`; they cannot be sized without a window id.\n\n| Field                           | Type            | Meaning                                                                          |\n| ------------------------------- | --------------- | -------------------------------------------------------------------------------- |\n| `value`                         | string          | The segment key to send as `audience`.                                           |\n| `label`, `description`          | string          | The words the dashboard shows, in the creator's language.                        |\n| `requires_pass_window`          | boolean         | Whether the segment needs a `pass_window_id`.                                    |\n| `supports_plan_filter`          | boolean         | Whether `plan_id` is accepted. False for `lead` and the pass segments.           |\n| `requires_expiring_within_days` | boolean         | Whether the segment reads a horizon. True only for `expiring_soon`.              |\n| `recipient_estimate`            | integer or null | Who the segment reaches right now; null where a window must be named first.      |",
                "summary": "List every audience",
                "tags": [
                    "Broadcasts"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Every segment with its label, its rules and a recipient estimate where one can be given without a window.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {}
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "value": "customer",
                                                    "label": "Customers Only",
                                                    "description": "Members holding a paid subscription right now.",
                                                    "requires_pass_window": false,
                                                    "supports_plan_filter": true,
                                                    "requires_expiring_within_days": false,
                                                    "recipient_estimate": 128
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "broadcast:send"
                ],
                "x-mcp-tools": [
                    "list_broadcast_audiences"
                ]
            }
        },
        "/v1/projects/{project}/broadcasts/preview": {
            "get": {
                "operationId": "v1.broadcasts.preview",
                "description": "Sizes a broadcast without sending it. The dashboard shows this before the confirm button, and an API caller needs the same safety rail.\n\n```bash\ncurl \"https://api.subscriby.net/v1/projects/$PROJECT_ID/broadcasts/preview?audience=customer&plan_id=$PLAN_ID\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe preview accepts the same `audience`, `pass_window_id`, `plan_id` and `expiring_within_days` as the send, and applies them identically, segments, plan narrowing and recipient rules alike, so a preview and the send it precedes can never describe different audiences. The fields answer the same as the send's, minus `status`.",
                "summary": "Preview an audience",
                "tags": [
                    "Broadcasts"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "audience",
                        "in": "query",
                        "description": "The segment to size: `all` (the default), `customer`, `trialing`, `lead`, `churned`, `expiring_soon`, `cancelled_still_active`, `paused`, `trialing_cardless`, `all_pass_holders`, `all_pass_holders_not_in_queue`, `pass_holders` or `pass_holders_not_in_queue`. An unknown value is `422` with `reason: unknown_audience` and the supported list.",
                        "schema": {
                            "type": "string",
                            "default": "all"
                        }
                    },
                    {
                        "name": "pass_window_id",
                        "in": "query",
                        "description": "The access window for `pass_holders` and `pass_holders_not_in_queue`; ignored by every other segment.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "plan_id",
                        "in": "query",
                        "description": "Narrow the segment to members whose subscription is on this plan. Refused for `lead` and the pass segments with `reason: plan_filter_unsupported`; a plan of another project is `reason: unknown_plan`.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "expiring_within_days",
                        "in": "query",
                        "description": "The horizon `expiring_soon` counts within, 1 to 90; a value outside the range clamps. Defaults to 7. Read by no other segment.",
                        "schema": {
                            "type": "integer",
                            "default": 7
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The recipient count and ETA for the segment as described.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "project_id": {
                                                    "type": "string",
                                                    "description": "The project the broadcast would go out from.",
                                                    "examples": [
                                                        "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                                    ]
                                                },
                                                "audience": {
                                                    "type": "string",
                                                    "description": "The segment as verified.",
                                                    "examples": [
                                                        "customer"
                                                    ]
                                                },
                                                "plan_id": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The plan filter as verified; null when none was sent.",
                                                    "examples": [
                                                        "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b"
                                                    ]
                                                },
                                                "expiring_within_days": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The horizon `expiring_soon` would use, after clamping; null for every other segment.",
                                                    "examples": [
                                                        null
                                                    ]
                                                },
                                                "recipient_estimate": {
                                                    "type": "integer",
                                                    "description": "How many members the segment resolves to right now.",
                                                    "examples": [
                                                        41
                                                    ],
                                                    "minimum": 0
                                                },
                                                "estimated_seconds": {
                                                    "type": "integer",
                                                    "description": "Roughly how long delivery would take at the platform's rate.",
                                                    "examples": [
                                                        2
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "project_id",
                                                "audience",
                                                "plan_id",
                                                "expiring_within_days",
                                                "recipient_estimate",
                                                "estimated_seconds"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "audience": "customer",
                                                "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "expiring_within_days": null,
                                                "recipient_estimate": 41,
                                                "estimated_seconds": 2
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: with `error.context.reason` of `unknown_audience` (the context also lists `supported` values), `plan_filter_unsupported` or `unknown_plan`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "broadcast:send"
                ],
                "x-mcp-tools": [
                    "preview_broadcast_audience"
                ]
            }
        },
        "/v1/projects/{project}/broadcasts": {
            "post": {
                "operationId": "v1.broadcasts.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/broadcasts \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"message\": \"<b>New drop is live</b>\\nDoors open at 19:00 UTC.\",\n    \"audience\": \"customer\"\n  }'\n```\n\n`202`, not `200`: the send is queued and runs in the background at roughly 28 messages a second to stay inside the platform's rate limit. The response describes what was *addressed*, not what was delivered.\n\n### Audience segments\n\n| Segment                          | Who it addresses                                                                          |\n| -------------------------------- | ----------------------------------------------------------------------------------------- |\n| `all`                            | Every member reachable on the project's connector, whatever their status.                 |\n| `customer`                       | Members holding a paid subscription right now.                                            |\n| `trialing`                       | Members currently inside a free trial.                                                    |\n| `lead`                           | Members who have used the project's bot but never subscribed.                             |\n| `churned`                        | Members who were customers and are not any more.                                          |\n| `expiring_soon`                  | Members whose subscription genuinely lapses within `expiring_within_days`.                |\n| `cancelled_still_active`         | Members who cancelled but have not run out yet: still reachable, still winnable.          |\n| `paused`                         | Members who paused their subscription rather than ending it.                              |\n| `trialing_cardless`              | Members trialing without a card on file, who will not convert on their own.               |\n| `all_pass_holders`               | Everyone holding a valid pass for any upcoming window.                                    |\n| `all_pass_holders_not_in_queue`  | Everyone who has not tapped their invite link, across every upcoming window.              |\n| `pass_holders`                   | Everyone holding a valid pass for one access window you choose (`pass_window_id`).        |\n| `pass_holders_not_in_queue`      | Holders of one window you choose who have not tapped their invite link yet.               |\n\nA member is a recipient only if they have a linked chat **on that project's connector**. Members with no chat, or whose chat belongs to a different installation, are excluded silently, which is why `recipient_estimate` is frequently well below a project's total membership.\n\n> **An auto-renewing subscription is never `expiring_soon`.** A subscription's `ends_at` is rewritten to the new period end on every renewal, so a date inside the horizon describes an auto-renewing member's next **invoice** rather than an expiry. Counting it would place every monthly subscriber in this segment once a month. A member is counted only when their access genuinely lapses: they have cancelled, or the plan is not recurring.\n\n### Narrowing a segment to a plan\n\n`plan_id` **composes** with `audience` rather than replacing it:\n\n| Request                                     | Who it addresses                         |\n| ------------------------------------------- | ---------------------------------------- |\n| `audience=customer` + `plan_id=<gold>`      | People paying for Gold right now.        |\n| `audience=churned` + `plan_id=<gold>`       | People who held Gold and left.           |\n| `audience=paused` + `plan_id=<gold>`        | People whose *paused* plan is Gold.      |\n| `audience=expiring_soon` + `plan_id=<gold>` | Gold members lapsing inside the horizon. |\n\nThe plan and the state describe the **same subscription**, so a member paying for Silver who once trialled Gold is not matched by the first row. `churned` is the deliberate exception in the other direction: the subscription proving they held the plan is the one that ended, so it is not required to be live.\n\nA `plan_id` sent with `lead` or a pass segment is **refused with `422` and `reason: plan_filter_unsupported`**, not ignored. Silently dropping it would return a recipient count for a different audience than the request described, and a caller has no way to notice.\n\n### Message formatting\n\nThe body is reduced to the HTML subset the delivering connector accepts before sending; for the messaging connector that is `<b>`, `<strong>`, `<i>`, `<em>`, `<u>`, `<ins>`, `<s>`, `<strike>`, `<del>`, `<a>`, `<code>`, `<pre>`, `<blockquote>` and `<tg-spoiler>`. Anything else is **stripped, not escaped**: the platform rejects an entire message containing an unknown tag, so removing it is what keeps the message deliverable.\n\nThe 4,096-character limit is the platform's own. A longer body is refused here rather than being truncated per recipient.\n\n### Refusals\n\nEvery `422` is refused **before** anything is queued. The underlying job re-checks the same conditions and aborts silently, which is correct for a background job and wrong for an API caller, so the endpoint rejects them up front rather than returning `202` for a send that could never leave. A segment that resolves to zero recipients is the send action's own refusal, shared with the dashboard: it is not queued.",
                "summary": "Send a broadcast",
                "tags": [
                    "Broadcasts"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreBroadcastRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "202 with the segment, the verified filters, the recipient count and the ETA.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "project_id": {
                                                    "type": "string",
                                                    "description": "The project the broadcast goes out from.",
                                                    "examples": [
                                                        "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                                    ]
                                                },
                                                "audience": {
                                                    "type": "string",
                                                    "description": "The segment as verified.",
                                                    "examples": [
                                                        "customer"
                                                    ]
                                                },
                                                "pass_window_id": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The window a pass segment addresses; null for every other segment.",
                                                    "examples": [
                                                        null
                                                    ]
                                                },
                                                "plan_id": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The plan filter as verified; null when none was sent.",
                                                    "examples": [
                                                        null
                                                    ]
                                                },
                                                "expiring_within_days": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The horizon `expiring_soon` used; null for every other segment.",
                                                    "examples": [
                                                        null
                                                    ]
                                                },
                                                "recipient_estimate": {
                                                    "type": "integer",
                                                    "description": "How many members the segment resolved to when the send was queued.",
                                                    "examples": [
                                                        128
                                                    ],
                                                    "minimum": 0
                                                },
                                                "estimated_seconds": {
                                                    "type": "integer",
                                                    "description": "Roughly how long delivery will take at the platform's rate.",
                                                    "examples": [
                                                        5
                                                    ]
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "Always `queued`.",
                                                    "const": "queued",
                                                    "examples": [
                                                        "queued"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "project_id",
                                                "audience",
                                                "pass_window_id",
                                                "plan_id",
                                                "expiring_within_days",
                                                "recipient_estimate",
                                                "estimated_seconds",
                                                "status"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "audience": "customer",
                                                "pass_window_id": null,
                                                "plan_id": null,
                                                "expiring_within_days": null,
                                                "recipient_estimate": 128,
                                                "estimated_seconds": 5,
                                                "status": "queued"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: with `error.context.reason` of `no_connected_bot` (the project has no connector connected, so it has no way to deliver), `missing_capability` (a pass segment on a project whose plan no longer includes passes), `pass_window_required` (a single-window segment with no `pass_window_id`), `unknown_audience` (the context lists the `supported` values), `plan_filter_unsupported` (a `plan_id` with `lead` or a pass segment) or `unknown_plan` (the `plan_id` is not this project's); or with no reason when the segment holds nobody right now, in which case `error.message` says which.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "broadcast:send"
                ],
                "x-webhook-events": [
                    "broadcast.queued",
                    "broadcast.completed"
                ],
                "x-mcp-tools": [
                    "broadcast_message"
                ]
            }
        },
        "/v1/connectors": {
            "get": {
                "operationId": "v1.connectors.index",
                "description": "Every connector Subscriby knows, lane by lane, installable connectors first, each with its badges and, for a registered one, its whole manifest and the connect form. `?status=` narrows to one lane.\n\n```bash\ncurl https://api.subscriby.net/v1/connectors \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nCards come lane by lane, installable connectors first; within a lane the most installed connector comes first (`installations`, the number of projects running it today, uninstalled rows excluded) and the name breaks ties. The public and in-app directories offer the same order plus Newest (`added_at`) and Name, and filter on `official`, `installable` and `category`; a client sorts and filters on the same fields.\n\n### Lanes and badges\n\n| `status`         | `status_label`    | Meaning                                                                                        |\n| ---------------- | ----------------- | ---------------------------------------------------------------------------------------------- |\n| `available`      | Available Now     | A package is present and configuration offers it; `installable` is `true`.                     |\n| `beta`           | Experimental      | Available, and flagged so; a badge on the card, never a gate. `installable` is `true`.         |\n| `paused`         | Paused            | Switched off during an incident. Nothing new is installed and sends queue until it is back.    |\n| `in_development` | Under Development | A package exists but configuration does not offer it yet (built, on staging, dark).            |\n| `coming_soon`    | Coming Soon       | A roadmap entry with no package behind it: the card, the category and an `eta` sentence only.  |\n\n`badges` are facts the platform stamps, never a package's own claim: `official` or `community` (who publishes it), `new` while the listing was added within the last sixty days, `trending` for the connector(s) creators installed most in the last thirty days. A `coming_soon` card carries none.",
                "summary": "List the connector directory",
                "tags": [
                    "Connectors"
                ],
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "description": "Narrow the directory to one lane: `available`, `beta`, `paused`, `in_development` or `coming_soon`. Omit for every lane. An unknown lane is `422 VALIDATION_FAILED` naming the accepted values.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "available"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Array of `ConnectorListingResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "$ref": "#/components/schemas/ConnectorListingResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "key": "example",
                                                    "name": "Example",
                                                    "vendor": "Subscriby",
                                                    "version": "1.0.0",
                                                    "status": "available",
                                                    "status_label": "Available Now",
                                                    "installable": true,
                                                    "official": true,
                                                    "badges": [
                                                        {
                                                            "key": "official",
                                                            "label": "Official"
                                                        },
                                                        {
                                                            "key": "trending",
                                                            "label": "Trending"
                                                        }
                                                    ],
                                                    "installations": 1284,
                                                    "category": "messaging",
                                                    "tagline": "Sell access to channels and groups through your own bot.",
                                                    "overview": "Connect a bot you created on the platform and Subscriby runs your membership there: …",
                                                    "icon": "example",
                                                    "eta": null,
                                                    "links": {
                                                        "documentation": "https://docs.subscriby.net/connectors/example",
                                                        "support": "mailto:support@subscriby.net",
                                                        "privacy": "https://example.org/privacy",
                                                        "terms": "https://example.org/tos",
                                                        "homepage": "https://example.org"
                                                    },
                                                    "added_at": "2025-04-21",
                                                    "changelog_url": "https://www.subscriby.net/blog",
                                                    "sign_in_required": false,
                                                    "portal_cta": {
                                                        "label": "Open the app",
                                                        "icon": "example"
                                                    },
                                                    "install_mode": "paste_credential",
                                                    "scopes": [
                                                        "project",
                                                        "platform"
                                                    ],
                                                    "resource_kinds": [
                                                        {
                                                            "kind": "channel",
                                                            "label": "Channel",
                                                            "portal_label": "Channel",
                                                            "icon": "megaphone",
                                                            "grant_mode": "bearer_link",
                                                            "supports_early_admission_hold": true,
                                                            "upgrades_from": null,
                                                            "plan_kinds": [
                                                                "one_time",
                                                                "recurring",
                                                                "pass",
                                                                "pass_series"
                                                            ]
                                                        },
                                                        {
                                                            "kind": "group",
                                                            "label": "Group",
                                                            "portal_label": "Group",
                                                            "icon": "user-group",
                                                            "grant_mode": "bearer_link",
                                                            "supports_early_admission_hold": true,
                                                            "upgrades_from": null,
                                                            "plan_kinds": [
                                                                "one_time",
                                                                "recurring",
                                                                "pass",
                                                                "pass_series"
                                                            ]
                                                        }
                                                    ],
                                                    "capabilities": [
                                                        "messaging",
                                                        "broadcasts",
                                                        "management_surface",
                                                        "copilot",
                                                        "access_control",
                                                        "early_admission_hold",
                                                        "support_relay",
                                                        "recovery_probes",
                                                        "recovery_standby_installations",
                                                        "recovery_resource_standby",
                                                        "recovery_mirror",
                                                        "recovery_identity_relink",
                                                        "creator_registration",
                                                        "portal_login",
                                                        "native_payments"
                                                    ],
                                                    "messaging": {
                                                        "max_length": 4096,
                                                        "buttons_per_row": 8,
                                                        "max_buttons": 100,
                                                        "callback_data_bytes": 64,
                                                        "supports_underline": true,
                                                        "supports_spoiler": true,
                                                        "supports_files": true
                                                    },
                                                    "pacing": {
                                                        "min_interval_microseconds": 35000,
                                                        "burst": 30,
                                                        "per_recipient_interval_microseconds": 1000000
                                                    },
                                                    "management_commands": [
                                                        "project_create",
                                                        "project_settings",
                                                        "project_delete",
                                                        "installation_connect",
                                                        "resource_link",
                                                        "resource_manage",
                                                        "plan_create",
                                                        "plan_manage",
                                                        "payment_method_setup",
                                                        "coupon_create",
                                                        "referral_program_manage",
                                                        "partner_program",
                                                        "access_codes_generate",
                                                        "broadcast",
                                                        "support_reply",
                                                        "support_relay_setup",
                                                        "recovery_relink",
                                                        "recovery_standby",
                                                        "recovery_replace_resource",
                                                        "account_recovery_email"
                                                    ],
                                                    "missing_commands": [
                                                        "manage_connectors",
                                                        "creator_tasks",
                                                        "recovery_status",
                                                        "set_alert_destination"
                                                    ],
                                                    "relay_modes": [
                                                        "owner_dm",
                                                        "forum_group"
                                                    ],
                                                    "recovery": {
                                                        "probes": true,
                                                        "standby_installations": true,
                                                        "resource_standby": true,
                                                        "mirror": true,
                                                        "identity_relink": true
                                                    },
                                                    "install_fields": [
                                                        {
                                                            "name": "instructions",
                                                            "type": "instructions",
                                                            "label": "Create a bot on the platform, then paste its token here.",
                                                            "help": "You can customise the bot afterwards …",
                                                            "required": false,
                                                            "rules": [],
                                                            "options": [],
                                                            "value": null,
                                                            "steps": [
                                                                "Open the platform's app and create a bot.",
                                                                "Copy the token it gives you and paste it in the input below.",
                                                                "Click on \":button\" to connect your bot to :app."
                                                            ],
                                                            "links": []
                                                        },
                                                        {
                                                            "name": "token",
                                                            "type": "secret",
                                                            "label": "Bot token",
                                                            "help": "Keep it secret: anyone who has it controls the bot.",
                                                            "required": true,
                                                            "rules": [
                                                                "string",
                                                                "regex:/^[0-9]{6,12}:[A-Za-z0-9_-]{30,64}$/"
                                                            ],
                                                            "options": [],
                                                            "value": null,
                                                            "steps": [],
                                                            "links": []
                                                        }
                                                    ],
                                                    "settings_fields": []
                                                },
                                                {
                                                    "key": "roadmap-example",
                                                    "name": "Roadmap Example",
                                                    "vendor": "Subscriby",
                                                    "version": null,
                                                    "status": "coming_soon",
                                                    "status_label": "Coming Soon",
                                                    "installable": false,
                                                    "official": false,
                                                    "badges": [],
                                                    "installations": 0,
                                                    "category": "messaging",
                                                    "tagline": "Gate channels and workspaces behind your plans, no manual invites.",
                                                    "overview": null,
                                                    "icon": "roadmap-example",
                                                    "eta": "Planned",
                                                    "links": null,
                                                    "added_at": null,
                                                    "changelog_url": null,
                                                    "sign_in_required": true,
                                                    "portal_cta": null,
                                                    "install_mode": null,
                                                    "scopes": [],
                                                    "resource_kinds": [],
                                                    "capabilities": [],
                                                    "messaging": null,
                                                    "pacing": null,
                                                    "management_commands": [],
                                                    "missing_commands": [],
                                                    "relay_modes": [],
                                                    "recovery": null,
                                                    "install_fields": [],
                                                    "settings_fields": []
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when `status` names no lane; `error.context.accepted` lists the lanes.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-connector:view-any"
                ],
                "x-mcp-tools": [
                    "list_connectors"
                ]
            }
        },
        "/v1/connectors/{key}": {
            "get": {
                "operationId": "v1.connectors.show",
                "description": "One card by key, registered or on the roadmap, in the shape the directory lists.\n\n```bash\ncurl https://api.subscriby.net/v1/connectors/example \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\n### The manifest\n\nEvery key from `install_mode` onward describes what a registered connector can do; a roadmap card has them `null` or empty.\n\n- `install_mode`: `paste_credential` (the creator pastes a token the platform issued), `oauth` (the creator authorises an app), `shared_platform` (Subscriby runs one shared presence; nothing to connect).\n- `scopes`: `project` for an installation a creator sets up on a project; `platform` for a presence Subscriby itself runs on the connector.\n- `resource_kinds`: the kinds of place the connector gates, with the creator-facing `label`, the `portal_label` members see, an `icon` slug, the `grant_mode` (`bearer_link`: a single-use link; `membership`: the connector admits the member itself; `role`: a role is granted; `creator_task`: the creator hands access over by hand), whether a grant can be held ahead of a pass window (`supports_early_admission_hold`), the kind of the same connector a place of this kind can be an in-place upgrade of (`upgrades_from`, or `null`), and the shapes of plan a place of the kind can be sold under (`plan_kinds`: `one_time`, `recurring`, `pass`, `pass_series`, in that order). A resource's `kind` on the [Resources endpoints](https://docs.subscriby.net/api/v1/reference/resources) is `<key>:<kind>`, and the same spelling is what a link request takes. Labels are translated into the token holder's language.\n- `capabilities`: the port families the connector implements: `messaging`, `broadcasts`, `access_control`, `early_admission_hold`, `support_relay`, `native_payments`, `portal_login`, `creator_registration`, `management_surface`, `copilot`, `recovery_probes`, `recovery_standby_installations`, `recovery_resource_standby`, `recovery_mirror`, `recovery_identity_relink`.\n- `messaging` and `pacing`: the limits every message and every bulk send is checked against.\n- `management_commands` and `missing_commands`: which core commands the connector's in-chat surface renders and which it does not; the docs' capability matrix and the Connectors tab show the gaps from these.\n- `recovery`: which Disaster Recovery facets the connector implements.\n- `portal_cta`: the button the member portal shows to open the connector (`label`, translated, and `icon`), or `null` when the connector has nowhere to open; the portal addresses it through the installation's start link.\n- `install_fields` and `settings_fields`: the declarative forms. Each field carries `type` (`text`, `secret`, `select`, `toggle`, `instructions`, `link`), a translated `label` and `help`, `required`, the validation `rules`, `options` for a select, a default `value`, the numbered walkthrough `steps` (with `:app` and `:button` placeholders for the app's name and the submit button's label) and `links` naming the text a renderer turns into a link. Render them in order and you have the connect form the dashboard shows.",
                "summary": "Get one connector",
                "tags": [
                    "Connectors"
                ],
                "parameters": [
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The connector key from the route.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the card.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ConnectorListingResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "key": "example",
                                                "name": "Example",
                                                "vendor": "Subscriby",
                                                "version": "1.0.0",
                                                "status": "available",
                                                "status_label": "Available Now",
                                                "installable": true,
                                                "official": true,
                                                "badges": [
                                                    {
                                                        "key": "official",
                                                        "label": "Official"
                                                    },
                                                    {
                                                        "key": "trending",
                                                        "label": "Trending"
                                                    }
                                                ],
                                                "installations": 1284,
                                                "category": "messaging",
                                                "tagline": "Sell access to channels and groups through your own bot.",
                                                "overview": "Connect a bot you created on the platform and Subscriby runs your membership there: …",
                                                "icon": "example",
                                                "eta": null,
                                                "links": {
                                                    "documentation": "https://docs.subscriby.net/connectors/example",
                                                    "support": "mailto:support@subscriby.net",
                                                    "privacy": "https://example.org/privacy",
                                                    "terms": "https://example.org/tos",
                                                    "homepage": "https://example.org"
                                                },
                                                "added_at": "2025-04-21",
                                                "changelog_url": "https://www.subscriby.net/blog",
                                                "sign_in_required": false,
                                                "portal_cta": {
                                                    "label": "Open the app",
                                                    "icon": "example"
                                                },
                                                "install_mode": "paste_credential",
                                                "scopes": [
                                                    "project",
                                                    "platform"
                                                ],
                                                "resource_kinds": [
                                                    {
                                                        "kind": "channel",
                                                        "label": "Channel",
                                                        "portal_label": "Channel",
                                                        "icon": "megaphone",
                                                        "grant_mode": "bearer_link",
                                                        "supports_early_admission_hold": true,
                                                        "upgrades_from": null,
                                                        "plan_kinds": [
                                                            "one_time",
                                                            "recurring",
                                                            "pass",
                                                            "pass_series"
                                                        ]
                                                    }
                                                ],
                                                "capabilities": [
                                                    "messaging",
                                                    "broadcasts",
                                                    "management_surface",
                                                    "copilot",
                                                    "access_control",
                                                    "early_admission_hold",
                                                    "support_relay",
                                                    "recovery_probes",
                                                    "recovery_standby_installations",
                                                    "recovery_resource_standby",
                                                    "recovery_mirror",
                                                    "recovery_identity_relink",
                                                    "creator_registration",
                                                    "portal_login",
                                                    "native_payments"
                                                ],
                                                "messaging": {
                                                    "max_length": 4096,
                                                    "buttons_per_row": 8,
                                                    "max_buttons": 100,
                                                    "callback_data_bytes": 64,
                                                    "supports_underline": true,
                                                    "supports_spoiler": true,
                                                    "supports_files": true
                                                },
                                                "pacing": {
                                                    "min_interval_microseconds": 35000,
                                                    "burst": 30,
                                                    "per_recipient_interval_microseconds": 1000000
                                                },
                                                "management_commands": [
                                                    "project_create",
                                                    "project_settings",
                                                    "project_delete",
                                                    "installation_connect",
                                                    "resource_link",
                                                    "resource_manage",
                                                    "plan_create",
                                                    "plan_manage",
                                                    "payment_method_setup",
                                                    "coupon_create",
                                                    "referral_program_manage",
                                                    "partner_program",
                                                    "access_codes_generate",
                                                    "broadcast",
                                                    "support_reply",
                                                    "support_relay_setup",
                                                    "recovery_relink",
                                                    "recovery_standby",
                                                    "recovery_replace_resource",
                                                    "account_recovery_email"
                                                ],
                                                "missing_commands": [
                                                    "manage_connectors",
                                                    "creator_tasks",
                                                    "recovery_status",
                                                    "set_alert_destination"
                                                ],
                                                "relay_modes": [
                                                    "owner_dm",
                                                    "forum_group"
                                                ],
                                                "recovery": {
                                                    "probes": true,
                                                    "standby_installations": true,
                                                    "resource_standby": true,
                                                    "mirror": true,
                                                    "identity_relink": true
                                                },
                                                "install_fields": [
                                                    {
                                                        "name": "token",
                                                        "type": "secret",
                                                        "label": "Bot token",
                                                        "help": "Keep it secret: anyone who has it controls the bot.",
                                                        "required": true,
                                                        "rules": [
                                                            "string",
                                                            "regex:/^[0-9]{6,12}:[A-Za-z0-9_-]{30,64}$/"
                                                        ],
                                                        "options": [],
                                                        "value": null,
                                                        "steps": [],
                                                        "links": []
                                                    }
                                                ],
                                                "settings_fields": []
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: when nothing is known by that key; `error.context.connector` echoes it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-connector:view-any"
                ],
                "x-mcp-tools": [
                    "get_connector"
                ]
            }
        },
        "/v1/projects/{project}/connectors": {
            "get": {
                "operationId": "v1.projects.connectors.index",
                "description": "Every installation the project holds, live and standby, oldest first.\n\n```bash\ncurl https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/connectors \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\n`role` is `live` for the one that acts and `standby` for the spare the Disaster Recovery Program keeps; `state` is `pending`, `connected`, `degraded` (the health probe found something wrong, `state_reason` and `state_detail` say what, `creator_actionable` whether the creator can fix it), `revoked` (the platform withdrew it) or `disconnected` (the creator did); `operational` is the one-word answer to \"can it act right now?\". `external_id`, `display_name`, `handle` and `avatar_url` are the platform's own account for the installation. Credentials and settings are never serialised.\n\n`sales_paused` and `outage` describe a connector outage: the platform refused this live installation outright (token revoked or regenerated, bot deleted). While `sales_paused` is `true`, `outage` carries the outage's `id`, the connector's `reason` code and `started_at`, and every plan that unlocks a place on this connector is refused at checkout with `422 VALIDATION_FAILED`; both go back to `false` and `null` when the installation answers again, is replaced or is uninstalled. [Connector outages](https://docs.subscriby.net/disaster-recovery/connector-outages) describes what members see and how they are compensated; [`connector.outage_opened`](https://docs.subscriby.net/webhooks/v1/events/connector/connector-outage-opened) and [`connector.outage_closed`](https://docs.subscriby.net/webhooks/v1/events/connector/connector-outage-closed) announce both ends.",
                "summary": "List a project's installations",
                "tags": [
                    "Connectors"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Array of `ConnectorInstallationResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "$ref": "#/components/schemas/ConnectorInstallationResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                                    "connector": "example",
                                                    "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                    "scope": "project",
                                                    "role": "live",
                                                    "state": "connected",
                                                    "state_reason": null,
                                                    "state_detail": null,
                                                    "creator_actionable": false,
                                                    "operational": true,
                                                    "external_id": "7123456789",
                                                    "display_name": "Research Bot",
                                                    "handle": "research_bot",
                                                    "avatar_url": null,
                                                    "health_checked_at": "2026-09-12T06:00:00Z",
                                                    "doctor_ran_at": "2026-09-12T06:00:00Z",
                                                    "doctor_healthy": true,
                                                    "connected_at": "2026-04-21T09:15:00Z",
                                                    "verified_at": "2026-09-12T06:00:00Z",
                                                    "revoked_at": null,
                                                    "disconnected_at": null,
                                                    "uninstalled_at": null,
                                                    "created_at": "2026-04-21T09:15:00Z",
                                                    "capabilities": {
                                                        "messaging": {
                                                            "enabled": true,
                                                            "toggleable": true
                                                        },
                                                        "access_control": {
                                                            "enabled": true,
                                                            "toggleable": false
                                                        }
                                                    },
                                                    "sales_paused": false,
                                                    "outage": null
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-connector:view-any"
                ],
                "x-mcp-tools": [
                    "list_connector_installations"
                ]
            }
        },
        "/v1/projects/{project}/connectors/{key}/installation": {
            "get": {
                "operationId": "v1.projects.connectors.installation",
                "description": "The project's installation of that connector in the live role, in whatever state, in the shape the installations list describes.\n\n```bash\ncurl https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/connectors/example/installation \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```",
                "summary": "Get a project's installation of a connector",
                "tags": [
                    "Connectors"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The connector key from the route.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the installation.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ConnectorInstallationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                                "connector": "example",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "scope": "project",
                                                "role": "live",
                                                "state": "connected",
                                                "state_reason": null,
                                                "state_detail": null,
                                                "creator_actionable": false,
                                                "operational": true,
                                                "external_id": "7123456789",
                                                "display_name": "Research Bot",
                                                "handle": "research_bot",
                                                "avatar_url": null,
                                                "health_checked_at": "2026-09-12T06:00:00Z",
                                                "doctor_ran_at": "2026-09-12T06:00:00Z",
                                                "doctor_healthy": true,
                                                "connected_at": "2026-04-21T09:15:00Z",
                                                "verified_at": "2026-09-12T06:00:00Z",
                                                "revoked_at": null,
                                                "disconnected_at": null,
                                                "uninstalled_at": null,
                                                "created_at": "2026-04-21T09:15:00Z",
                                                "capabilities": {
                                                    "messaging": {
                                                        "enabled": true,
                                                        "toggleable": true
                                                    },
                                                    "access_control": {
                                                        "enabled": true,
                                                        "toggleable": false
                                                    }
                                                },
                                                "sales_paused": false,
                                                "outage": null
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: with `reason: unknown_connector` when the key names no connector at all, so a client can tell a typo from a connector that is not set up here. `CONNECTOR_NOT_INSTALLED`: when the connector exists but the project does not run it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_NOT_INSTALLED": {
                                        "summary": "CONNECTOR_NOT_INSTALLED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_NOT_INSTALLED",
                                                "message": "That connector is not installed on this project.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-not-installed",
                                                "remediation": "Install the connector on the project first (POST /v1/projects/{project}/connectors/{key}), or read GET /v1/projects/{project}/connectors for what is installed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-connector:view"
                ],
                "x-mcp-tools": [
                    "get_connector_installation"
                ]
            },
            "delete": {
                "operationId": "v1.projects.connectors.disconnect",
                "description": "```bash\ncurl -X DELETE https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/connectors/example/installation \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nThe connector withdraws the installation on its platform, the credentials are wiped and the installation turns `disconnected`; the row stays and can be connected again from the dashboard. Grants, resources, plans and identities are untouched, and members keep the access they hold. Answers `204`; an installation already disconnected is left alone. Disconnecting is not uninstalling: uninstalling, with its impact preview over the plans it would empty, is the separate act below.",
                "summary": "Disconnect an installation",
                "tags": [
                    "Connectors"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The connector key from the route.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: with `reason: unknown_connector`, or `404 CONNECTOR_NOT_INSTALLED` when the project does not run the connector.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-connector:delete"
                ],
                "x-webhook-events": [
                    "connector.disconnected"
                ],
                "x-mcp-tools": [
                    "disconnect_connector"
                ]
            }
        },
        "/v1/projects/{project}/connectors/{key}/uninstall-preview": {
            "get": {
                "operationId": "v1.projects.connectors.uninstall-preview",
                "description": "Uninstall deletes nothing and touches no money by itself, and it is always previewed first:\n\n```bash\ncurl https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/connectors/example/uninstall-preview \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\n- `resources` are the connector's on the project (manual perks are never among them); they will be deactivated and marked `detached`, their external ids kept.\n- `live_grants` are the pending, held and granted grants on those resources; each is revoked with reason `connector_uninstalled` and fires `member.resource_removed`.\n- `emptied_plans` are the plans that would keep no active grantable resource; `recurring_subscriptions` and `one_time_subscriptions` are the live purchases on them, `affected_subscription_ids` names them.\n- `upcoming_windows`, `open_support_threads` and `member_identities` are informational: pass windows are never cancelled for you (cancel them from the pass window endpoints, which handle refunds), support threads lose their reach, and member accounts are never removed.\n- `options` are the two opt-ins with their defaults, exactly the names the `DELETE` takes.",
                "summary": "Preview an uninstall",
                "tags": [
                    "Connectors"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The connector key from the route.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the preview.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/UninstallPreviewResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "installation": {
                                                    "id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                                    "connector": "example",
                                                    "state": "connected",
                                                    "operational": true
                                                },
                                                "connector": "example",
                                                "resources": [
                                                    {
                                                        "id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                        "title": "Members Lounge",
                                                        "kind": "example:role",
                                                        "active": true
                                                    }
                                                ],
                                                "live_grants": 41,
                                                "emptied_plans": [
                                                    {
                                                        "id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                        "name": "Lounge Monthly",
                                                        "active": true,
                                                        "recurring": true
                                                    }
                                                ],
                                                "recurring_subscriptions": 17,
                                                "one_time_subscriptions": 3,
                                                "affected_subscription_ids": [
                                                    "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                                                ],
                                                "upcoming_windows": 0,
                                                "open_support_threads": 2,
                                                "member_identities": 44,
                                                "empties_plans": true,
                                                "options": {
                                                    "unpublish_emptied_plans": true,
                                                    "cancel_recurring_subscriptions": true
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: with `reason: unknown_connector`, or `404 CONNECTOR_NOT_INSTALLED` when the project does not run the connector.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-connector:view"
                ],
                "x-mcp-tools": [
                    "get_connector_uninstall_preview"
                ]
            }
        },
        "/v1/projects/{project}/connectors/{key}": {
            "post": {
                "operationId": "v1.projects.connectors.install",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/connectors/example \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nInstalling and connecting are two acts. Installing says \"this project runs this connector\" and opens a **pending** installation with no credentials (`201` with the installation; `200` with the existing one when it was already installed, nothing changed). Connecting, which hands the connector the creator's credentials, stays on the dashboard, where the connector's declared `install_fields` are rendered and the platform is asked to describe the installation before anything is bound; a REST client cannot prove a credential is its own to bind. An uninstalled connector installed again comes back as pending with its settings kept.",
                "summary": "Install a connector",
                "tags": [
                    "Connectors"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The connector key from the route.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "201 with the installation; 200 when it was already installed.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `CONNECTOR_TIER_REQUIRED`: for a second distinct connector on the project when the **project owner's** plan lacks the `multi_connector` capability (Growth). The owner's plan is read, never the token holder's, because Teams lets a member run someone else's project.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: with `reason: unknown_connector` when the key names no connector.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`CONNECTOR_UNAVAILABLE`: when the key names no connector creators may install today: only a card whose `installable` is `true` qualifies; `error.context.connector` echoes the key.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "CONNECTOR_UNAVAILABLE": {
                                        "summary": "CONNECTOR_UNAVAILABLE",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_UNAVAILABLE",
                                                "message": "That connector is not one creators may install today.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-unavailable",
                                                "remediation": "Read GET /v1/connectors: only a connector whose status is available or beta can be installed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-connector:create"
                ],
                "x-webhook-events": [
                    "connector.installed"
                ],
                "x-mcp-tools": [
                    "install_connector"
                ]
            },
            "delete": {
                "operationId": "v1.projects.connectors.uninstall",
                "description": "```bash\ncurl -X DELETE https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/connectors/example \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"unpublish_emptied_plans\": true, \"cancel_recurring_subscriptions\": false}'\n```\n\nIn order: the connector puts every member outside while its credentials still work, the rows are retired in one transaction (grants revoked, resources detached, the installation kept with `uninstalled_at`), the connector withdraws the installation, and the two opt-ins run. `unpublish_emptied_plans` (default `true`) takes the emptied plans off sale, firing `plan.deactivated` per plan; `cancel_recurring_subscriptions` (default `true`) cancels their live recurring subscriptions at the end of the paid period, firing `subscription.cancelled` per subscription and emailing each member that their subscription will not renew. One-time and lifetime purchases are never cancelled; a refund stays the creator's call. Identities are never removed. `connector.uninstalled` fires with the counts. Installing the connector again brings the same installation back as pending with its settings kept.\n\nThe two opt-ins travel in the JSON body or as query parameters; on by default, they only need sending to switch one off.",
                "summary": "Uninstall a connector",
                "tags": [
                    "Connectors"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The connector key from the route.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "unpublish_emptied_plans",
                        "in": "query",
                        "description": "Take the plans the uninstall leaves with nothing to grant off sale, firing `plan.deactivated` per plan. Defaults to true; send `false` to leave them on sale.",
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "name": "cancel_recurring_subscriptions",
                        "in": "query",
                        "description": "Cancel the live recurring subscriptions on those plans at the end of their paid period, firing `subscription.cancelled` per subscription and emailing each member. Defaults to true; one-time and lifetime purchases are never cancelled.",
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the report.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/UninstallReportResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "installation": {
                                                    "id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                                    "connector": "example",
                                                    "state": "disconnected",
                                                    "operational": false,
                                                    "uninstalled_at": "2026-09-12T11:30:00+00:00"
                                                },
                                                "connector": "example",
                                                "grants_revoked": 41,
                                                "resources_detached": 2,
                                                "plans_unpublished": 1,
                                                "subscriptions_cancelled": 0,
                                                "members_notified": 0
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: with `reason: unknown_connector`, or `404 CONNECTOR_NOT_INSTALLED` when the project does not run the connector.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-connector:delete"
                ],
                "x-webhook-events": [
                    "connector.uninstalled",
                    "member.resource_removed",
                    "plan.deactivated",
                    "subscription.cancelled"
                ],
                "x-mcp-tools": [
                    "uninstall_connector"
                ]
            }
        },
        "/v1/projects/{project}/connectors/{key}/installation/verify": {
            "post": {
                "operationId": "v1.projects.connectors.verify",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/connectors/example/installation/verify \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nA fresh probe rather than the hourly one: the connector is asked whether the installation still answers and the verdict is recorded, so `state` becomes `connected`, `degraded` (with `state_reason`, `state_detail` and `creator_actionable`) or `revoked`, and `health_checked_at` is stamped. Answers `200` with the installation. A `pending` installation has nothing to verify and is returned as it is. `connector.status_changed` fires only when the state moved.",
                "summary": "Verify an installation",
                "tags": [
                    "Connectors"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The connector key from the route.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the installation as recorded.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ConnectorInstallationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: with `reason: unknown_connector`, or `404 CONNECTOR_NOT_INSTALLED` when the project does not run the connector.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-connector:update"
                ],
                "x-webhook-events": [
                    "connector.status_changed"
                ],
                "x-mcp-tools": [
                    "verify_connector_installation"
                ]
            }
        },
        "/v1/projects/{project}/connectors/{key}/installation/doctor": {
            "post": {
                "operationId": "v1.projects.connectors.doctor",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/connectors/example/installation/doctor \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nThe **Run Doctor** button of the dashboard. The installation is verified exactly as the verify endpoint does it, then the connector is asked about every resource the installation gates, and the answer is one report: a finding for the installation, then one per resource, each with a `severity` (`ok`, `warning`, `critical`), the connector's own `state` word, a sentence in the creator's language, whether the creator can fix it (`creator_actionable`) and where (`fix_url`). A resource the connector has no place for is a `warning`, never silence. `healthy` is `true` when every finding is `ok`.\n\nThe report is kept on the installation (`doctor_ran_at` and `doctor_healthy` on the installation object) and `connector.doctor_completed` fires only when the findings differ from the previous run's.",
                "summary": "Run the connector doctor",
                "tags": [
                    "Connectors"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The connector key.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the report.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/DoctorReportResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "installation_id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                                "connector": "example",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "ran_at": "2026-09-12T10:07:00Z",
                                                "healthy": false,
                                                "critical": 1,
                                                "warnings": 0,
                                                "findings": [
                                                    {
                                                        "key": "installation",
                                                        "kind": "installation",
                                                        "severity": "ok",
                                                        "severity_label": "OK",
                                                        "subject": "Research Bot",
                                                        "state": "connected",
                                                        "message": "The connector still answers for this installation.",
                                                        "creator_actionable": false,
                                                        "fix_url": null,
                                                        "resource_id": null
                                                    },
                                                    {
                                                        "key": "resource:b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                        "kind": "resource",
                                                        "severity": "critical",
                                                        "severity_label": "Critical",
                                                        "subject": "Premium Channel",
                                                        "state": "not_member",
                                                        "message": "The bot was removed from this channel.",
                                                        "creator_actionable": true,
                                                        "fix_url": "https://app.subscriby.net/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/resources",
                                                        "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6"
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: with `reason: unknown_connector`, or `404 CONNECTOR_NOT_INSTALLED` when the project does not run the connector.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-connector:update"
                ],
                "x-webhook-events": [
                    "connector.doctor_completed"
                ],
                "x-mcp-tools": [
                    "run_connector_doctor"
                ]
            }
        },
        "/v1/projects/{project}/connectors/{key}/installation/restore-access": {
            "post": {
                "operationId": "v1.projects.connectors.restore-access",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/connectors/example/installation/restore-access \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nThe **Restore Access** item of the dashboard's Connectors tab, offered while an uninstall has left the project detached places on the connector. Once the connector is installed and connected again, every detached place is asked about through the connector; the ones it still controls are made active and healthy again, and every live purchase of a plan that grants them is handed fresh access: only the grants the purchase lacks are issued, which are exactly the ones the uninstall took away, and `member.resource_added` fires per grant. A place the connector no longer controls stays detached for the doctor to explain. Plans the uninstall took off sale stay off sale until you publish them again.",
                "summary": "Restore access after a reinstall",
                "tags": [
                    "Connectors"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The connector key.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the report.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RestoreReportResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "installation": {
                                                    "id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                                    "connector": "example",
                                                    "state": "connected"
                                                },
                                                "connector": "example",
                                                "resources": [
                                                    {
                                                        "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                        "title": "Premium Channel",
                                                        "restored": true
                                                    },
                                                    {
                                                        "resource_id": "0d4a7e19-5c2b-4f83-9a61-2e8b7c3d5f10",
                                                        "title": "Archive Group",
                                                        "restored": false
                                                    }
                                                ],
                                                "resources_reactivated": 1,
                                                "resources_still_detached": 1,
                                                "subscriptions_reissued": 14
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: with `reason: unknown_connector`, or `404 CONNECTOR_NOT_INSTALLED` when the project has no installation of the connector.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`CONNECTOR_NOT_CONNECTED`: while the installation is pending or disconnected.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "CONNECTOR_NOT_CONNECTED": {
                                        "summary": "CONNECTOR_NOT_CONNECTED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_NOT_CONNECTED",
                                                "message": "That connector is installed on this project but not connected, so it cannot be asked.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-not-connected",
                                                "remediation": "Connect the installation from the project's Connectors page, verify it (POST /v1/projects/{project}/connectors/{key}/installation/verify), then retry.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-connector:update"
                ],
                "x-webhook-events": [
                    "member.resource_added"
                ],
                "x-mcp-tools": [
                    "restore_connector_access"
                ]
            }
        },
        "/v1/projects/{project}/connectors/{key}/installation/settings": {
            "patch": {
                "operationId": "v1.projects.connectors.settings",
                "description": "```bash\ncurl -X PATCH https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/connectors/example/installation/settings \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"settings\": {\"greeting\": \"Welcome aboard\"}, \"capabilities\": {\"broadcasts\": false}}'\n```\n\n`settings` is an object keyed by the field names the connector declares in its `settings_fields` (read them from the card). Every declared rule runs; a key the connector never declared is `422 VALIDATION_FAILED` naming it; fields left out keep their value.\n\n`capabilities` is an object keyed by capability to `true` or `false`: the project's switches for what the connector may do on this installation. A project keeps a connector for access alone by switching off `messaging`, `broadcasts`, `support_relay`, `native_payments` or any `recovery_*` facet; every core surface asks the switch before it invokes the connector, so a switched-off broadcast is refused before it is queued and a switched-off health check is skipped. A capability the connector does not declare, or one that cannot be switched off (`access_control`, `early_admission_hold`, `management_surface`, `portal_login`, `creator_registration`), is `422 VALIDATION_FAILED` naming it; switches left out keep their value. At least one of `settings` and `capabilities` is required.\n\nAnswers `200` with the installation, which never carries the settings themselves because a settings field may be a secret, but does carry `capabilities`: every capability the connector declares, each with `enabled` and `toggleable`. `connector.settings_updated` fires naming the fields and the switches (`capabilities.<key>`) that changed, only when something did.",
                "summary": "Change an installation's settings",
                "tags": [
                    "Connectors"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The connector key from the route.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateInstallationSettingsRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "200 with the installation.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ConnectorInstallationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: with `reason: unknown_connector`, or `404 CONNECTOR_NOT_INSTALLED` when the project does not run the connector.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when both `settings` and `capabilities` are missing, a settings key the connector never declared is sent, a declared rule fails, or a capability is undeclared or cannot be switched off; `error.fields` names the key.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-connector:update"
                ],
                "x-webhook-events": [
                    "connector.settings_updated"
                ],
                "x-mcp-tools": [
                    "update_connector_installation_settings"
                ]
            }
        },
        "/v1/me/copilot-credits": {
            "get": {
                "operationId": "v1.me.copilot-credits.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/me/copilot-credits \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nOne object: the `balance` split into free and paid with what lapses next, this month's free `allowance` used and left, this month's usage per kind, the per-unit prices, the `packs` on sale in this environment and the `settings` the write below changes. An agent asking whether it can afford a turn needs only this.\n\n`exhausted` is true when the pool has nothing left; the monthly allowance may still cover a turn, which is why the Copilot keeps answering on a Free plan with an empty pool. `paid_spent_this_month_cents` is the figure the cap in `settings` is measured against.",
                "summary": "Your Copilot Credits",
                "tags": [
                    "Copilot Credits"
                ],
                "responses": {
                    "200": {
                        "description": "The overview: balance, allowance, this month, prices, packs and settings.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/CopilotCreditOverviewResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "balance": {
                                                    "total_cents": 3250,
                                                    "free_cents": 750,
                                                    "paid_cents": 2500,
                                                    "lapsing_cents": 500,
                                                    "lapsing_at": "2027-01-16T00:00:00+00:00",
                                                    "exhausted": false
                                                },
                                                "allowance": {
                                                    "period_start": "2026-10-01",
                                                    "turns_used": 12,
                                                    "turns_limit": 25,
                                                    "turns_left": 13,
                                                    "answers_used": 40,
                                                    "answers_limit": 250,
                                                    "answers_left": 210
                                                },
                                                "turns_this_month": 12,
                                                "suggestions_this_month": 4,
                                                "answers_this_month": 40,
                                                "paid_spent_this_month_cents": 0,
                                                "price_turn_cents": 10,
                                                "price_suggestion_cents": 5,
                                                "price_answer_cents": 1,
                                                "long_turn_steps": 4,
                                                "max_turn_steps": 8,
                                                "low_balance_cents": 500,
                                                "packs": [
                                                    {
                                                        "pack": "starter",
                                                        "label": "Starter Pack",
                                                        "paid_cents": 1000,
                                                        "bonus_cents": 0,
                                                        "total_cents": 1000
                                                    },
                                                    {
                                                        "pack": "regular",
                                                        "label": "Regular Pack",
                                                        "paid_cents": 2500,
                                                        "bonus_cents": 250,
                                                        "total_cents": 2750
                                                    },
                                                    {
                                                        "pack": "plus",
                                                        "label": "Plus Pack",
                                                        "paid_cents": 5000,
                                                        "bonus_cents": 750,
                                                        "total_cents": 5750
                                                    },
                                                    {
                                                        "pack": "max",
                                                        "label": "Max Pack",
                                                        "paid_cents": 10000,
                                                        "bonus_cents": 1500,
                                                        "total_cents": 11500
                                                    }
                                                ],
                                                "settings": {
                                                    "auto_topup_pack": "regular",
                                                    "auto_topup_pack_label": "Regular Pack",
                                                    "auto_topup_below_cents": 500,
                                                    "monthly_spend_cap_cents": 2000,
                                                    "auto_topup_paused_at": null,
                                                    "updated_at": "2026-10-12T09:20:00+00:00"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-mcp-tools": [
                    "get_copilot_credits"
                ]
            }
        },
        "/v1/me/copilot-credits/statement": {
            "get": {
                "operationId": "v1.me.copilot-credits.statement",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/me/copilot-credits/statement?per_page=50\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nPages the last twelve months of lines, newest first: every pack bought and its bonus, every promotion and goodwill grant, every refund and lapse, and each month's usage per kind. Credits are positive and debits negative, so summing `cents` follows the balance. `sort_by` and `sort_direction` are accepted and ignored: a statement is always newest first.",
                "summary": "Your statement",
                "tags": [
                    "Copilot Credits"
                ],
                "parameters": [
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page of statement lines, newest first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/CopilotCreditStatementEntryResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL.",
                                                    "examples": [
                                                        "…"
                                                    ]
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL.",
                                                    "examples": [
                                                        "…"
                                                    ]
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page.",
                                                    "examples": [
                                                        null
                                                    ]
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page.",
                                                    "examples": [
                                                        null
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs.",
                                                    "examples": [
                                                        "…"
                                                    ]
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "examples": [
                                                        50
                                                    ],
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "examples": [
                                                        3
                                                    ],
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "examples": [
                                                        3
                                                    ],
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "kind": "usage",
                                                    "kind_label": "Copilot Usage",
                                                    "cents": -120,
                                                    "at": "2026-10-01T00:00:00+00:00",
                                                    "label": "Copilot Turns, October 2026",
                                                    "expires_at": null,
                                                    "units": 12,
                                                    "usage_kind": "operator_turn",
                                                    "usage_kind_label": "Copilot Turns"
                                                },
                                                {
                                                    "kind": "bonus",
                                                    "kind_label": "Pack Bonus",
                                                    "cents": 250,
                                                    "at": "2026-09-28T14:02:11+00:00",
                                                    "label": "Regular pack bonus",
                                                    "expires_at": null,
                                                    "units": null,
                                                    "usage_kind": null,
                                                    "usage_kind_label": null
                                                },
                                                {
                                                    "kind": "purchase",
                                                    "kind_label": "Pack Bought",
                                                    "cents": 2500,
                                                    "at": "2026-09-28T14:02:11+00:00",
                                                    "label": "Regular pack",
                                                    "expires_at": null,
                                                    "units": null,
                                                    "usage_kind": null,
                                                    "usage_kind_label": null
                                                }
                                            ],
                                            "links": {
                                                "first": "…",
                                                "last": "…",
                                                "prev": null,
                                                "next": null
                                            },
                                            "meta": {
                                                "current_page": 1,
                                                "from": 1,
                                                "last_page": 1,
                                                "path": "…",
                                                "per_page": 50,
                                                "to": 3,
                                                "total": 3
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-mcp-tools": [
                    "list_copilot_credits_statement"
                ]
            }
        },
        "/v1/me/copilot-credits/packs": {
            "post": {
                "operationId": "v1.me.copilot-credits.packs.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/me/copilot-credits/packs \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"pack\": \"regular\" }'\n```\n\nAnswers `201` with the pack and the Stripe Checkout URL to send the creator to. The session pays with their card and saves it for the auto top-up; the pending purchase is credited, bonus included, when Stripe reports the session paid, and `copilot_credit.purchased` fires then. A session nobody pays expires on its own and grants nothing.",
                "summary": "Buy a pack",
                "tags": [
                    "Copilot Credits"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StartCopilotCreditPackRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The pack and the Checkout URL.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/CopilotCreditPackCheckoutResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "pack": "regular",
                                                "label": "Regular Pack",
                                                "paid_cents": 2500,
                                                "bonus_cents": 250,
                                                "checkout_url": "https://checkout.stripe.com/c/pay/cs_live_…"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `pack` is not `starter`, `regular`, `plus` or `max`, or names a pack with no price in this environment.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:write"
                ],
                "x-mcp-tools": [
                    "create_copilot_credits_pack"
                ]
            }
        },
        "/v1/me/copilot-credits/settings": {
            "patch": {
                "operationId": "v1.me.copilot-credits.settings.update",
                "description": "```bash\ncurl -X PATCH https://api.subscriby.net/v1/me/copilot-credits/settings \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"auto_topup_pack\": \"regular\", \"auto_topup_below_cents\": 500 }'\n```\n\nAnswers `200` with the settings after the change. **Every field is optional and an omitted one keeps its stored value**, so `{ \"auto_topup_pack\": null }` switches the auto top-up off and changes nothing else. The bounds are the Billing dialog's: a threshold of $1 to $100 and a cap of $0 to $10,000, in cents. Saving the settings resumes an auto top-up a failed charge had paused.",
                "summary": "Change the auto top-up and the cap",
                "tags": [
                    "Copilot Credits"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateCopilotCreditSettingsRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The settings after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/CopilotCreditSettingsResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "auto_topup_pack": "regular",
                                                "auto_topup_pack_label": "Regular Pack",
                                                "auto_topup_below_cents": 500,
                                                "monthly_spend_cap_cents": 2000,
                                                "auto_topup_paused_at": null,
                                                "updated_at": "2026-10-20T08:15:00+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `auto_topup_pack` is not a pack on sale, `auto_topup_below_cents` is outside 100 to 10,000, `monthly_spend_cap_cents` is outside 0 to 1,000,000, or the auto top-up is switched on with no card on file.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:write"
                ],
                "x-mcp-tools": [
                    "update_copilot_credits_settings"
                ]
            }
        },
        "/v1/projects/{project}/coupons": {
            "get": {
                "operationId": "v1.coupons.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/coupons?active=true&per_page=25&page=1\" \\\n  -H \"Authorization: Bearer sbt_...\"\n```\n\nPages the project's coupons, newest first. `active` filters on the creator's on/off switch only; `code` finds one exact code.\n\n> `active=true` is not the same as redeemable. A coupon can be switched on and still not apply: outside its window, fully claimed, or capped for that subscriber. Read `redeemable` on each row for the combined answer.",
                "summary": "List a project's coupons",
                "tags": [
                    "Coupons"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "active",
                        "in": "query",
                        "description": "Keep only coupons whose on/off switch is in this position. Not the same as redeemable: read `redeemable` on each row for the combined answer.",
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "name": "code",
                        "in": "query",
                        "description": "Find one coupon by its exact code, compared in upper case.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "BLACKFRIDAY"
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/CouponResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-coupon:view-any"
                ],
                "x-mcp-tools": [
                    "list_coupons"
                ]
            },
            "post": {
                "operationId": "v1.coupons.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/coupons \\\n  -H \"Authorization: Bearer sbt_...\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"code\": \"BLACKFRIDAY\",\n    \"name\": \"Black Friday 2026\",\n    \"discount_type\": \"percentage\",\n    \"discount_value\": 25,\n    \"max_redemptions\": 500,\n    \"max_redemptions_per_user\": 1,\n    \"starts_at\": \"2026-11-27T00:00:00Z\",\n    \"expires_at\": \"2026-12-01T00:00:00Z\",\n    \"active\": true\n  }'\n```\n\nAnswers `201` with the coupon. `duration` is not yours to set: only first-payment discounts exist today, so it is always `once` on the way out.\n\n> **`code` is uppercased before the uniqueness check.** Sending `blackfriday` when `BLACKFRIDAY` exists in the project is a `422`, not a second coupon. Uniqueness is per project, so two different projects may both have `BLACKFRIDAY`.",
                "summary": "Create a coupon",
                "tags": [
                    "Coupons"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreCouponRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The new coupon.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/CouponResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: when the creator has neither the Coupons Addon nor a Growth plan.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when a field is invalid, the code is taken in the project, a fixed discount has no currency, or a percentage is above 100; `error.fields` names the key.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-coupon:create"
                ],
                "x-webhook-events": [
                    "coupon.created"
                ],
                "x-mcp-tools": [
                    "create_coupon"
                ]
            }
        },
        "/v1/projects/{project}/coupons/{coupon}": {
            "get": {
                "operationId": "v1.coupons.show",
                "description": "One coupon with its currency ISO code loaded. A coupon of another project, or a deleted one, is `404 RESOURCE_NOT_FOUND`.\n\n### Three fields that are easy to misread\n\n> **`plan_ids: []` means every plan, not no plans.** An empty array is how the coupon itself reads an empty plan relation: the code applies to **every** plan in the project, including plans added later. Treating it as \"restricted to nothing\" inverts the meaning.\n\n**`redemptions.remaining` is derived, not stored.** Prefer it over computing `max_redemptions - count` yourself. The quota counts settled redemptions *plus* reservations whose hold has not expired, so an in-flight checkout is already accounted for, and an abandoned one returns its slot without any sweeper job. Your own subtraction will disagree.\n\n**`discount.value` is a decimal string with four places**: `\"25.0000\"` for 25% off, `\"10.0000\"` for ten of the coupon's currency. Parse it as a decimal, never a float. `currency_id` is `null` on a percentage coupon and set on a fixed-amount one, because a percentage applies to a plan in any currency and a fixed amount only to plans priced in its own.\n\n`currency` (the ISO code) is present only when the relation is loaded: on a single read, a create and an update, not on every list row.",
                "summary": "Get a coupon",
                "tags": [
                    "Coupons"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "coupon",
                        "in": "path",
                        "required": true,
                        "description": "The coupon, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The coupon.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/CouponResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "4b9d3e08-a1f6-4275-9c83-7e01d6a2f594",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "code": "BLACKFRIDAY",
                                                "name": "Black Friday 2026",
                                                "discount": {
                                                    "type": "percentage",
                                                    "value": "25.0000",
                                                    "currency_id": null,
                                                    "currency": null
                                                },
                                                "duration": "once",
                                                "limits": {
                                                    "max_redemptions": 500,
                                                    "max_redemptions_per_user": 1,
                                                    "minimum_amount": null
                                                },
                                                "redemptions": {
                                                    "count": 137,
                                                    "remaining": 363,
                                                    "exhausted": false
                                                },
                                                "window": {
                                                    "starts_at": "2026-11-27T00:00:00+00:00",
                                                    "expires_at": "2026-12-01T00:00:00+00:00"
                                                },
                                                "plan_ids": [],
                                                "active": true,
                                                "redeemable": true,
                                                "created_at": "2026-11-20T09:14:02+00:00",
                                                "updated_at": "2026-11-24T16:41:11+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-coupon:view"
                ],
                "x-mcp-tools": [
                    "get_coupon"
                ]
            },
            "patch": {
                "operationId": "v1.coupons.update",
                "description": "Accepts the same fields as create, all optional. Changing terms is **not retroactive**: subscribers who already redeemed keep exactly what they paid, and the change applies to redemptions from that point on.\n\nRaising `max_redemptions` on an exhausted coupon makes it redeemable again. Lowering it below the current count does not claw anything back; the coupon simply reports `remaining: 0`. Answers `200` with the coupon.",
                "summary": "Update a coupon",
                "tags": [
                    "Coupons"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "coupon",
                        "in": "path",
                        "required": true,
                        "description": "The coupon, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateCouponRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The coupon after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/CouponResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: when the creator has neither the Coupons Addon nor a Growth plan.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when a field is invalid or the new code is taken by another live coupon of the project.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-coupon:update"
                ],
                "x-webhook-events": [
                    "coupon.updated"
                ],
                "x-mcp-tools": [
                    "update_coupon"
                ]
            },
            "delete": {
                "operationId": "v1.coupons.destroy",
                "description": "```bash\ncurl -X DELETE https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/coupons/4b9d3e08-a1f6-4275-9c83-7e01d6a2f594 \\\n  -H \"Authorization: Bearer sbt_...\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nRemoves the code and its redemption history; deactivating keeps both. Answers `204` with no body.\n\n> **A delete can be refused.** If any subscriber holds a live reservation, a checkout in flight with this discount already quoted to a payment provider, the delete answers `422` and asks you to deactivate instead.",
                "summary": "Delete a coupon",
                "tags": [
                    "Coupons"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "coupon",
                        "in": "path",
                        "required": true,
                        "description": "The coupon, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: when the creator has neither the Coupons Addon nor a Growth plan.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when a checkout with the code is still in flight; `error.context.coupon` carries the reason.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-coupon:delete"
                ],
                "x-webhook-events": [
                    "coupon.deleted"
                ],
                "x-mcp-tools": [
                    "delete_coupon"
                ]
            }
        },
        "/v1/projects/{project}/coupons/{coupon}/activate": {
            "post": {
                "operationId": "v1.coupons.activate",
                "description": "Switches the code on so new redemptions are accepted again, within its window and cap. Emits `coupon.activated` rather than `coupon.updated`, so an automation watching availability has one event to subscribe to. Answers `200` with the coupon.",
                "summary": "Activate a coupon",
                "tags": [
                    "Coupons"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "coupon",
                        "in": "path",
                        "required": true,
                        "description": "The coupon, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The coupon after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/CouponResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: when the creator has neither the Coupons Addon nor a Growth plan.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-coupon:update"
                ],
                "x-webhook-events": [
                    "coupon.activated"
                ],
                "x-mcp-tools": [
                    "activate_coupon"
                ]
            }
        },
        "/v1/projects/{project}/coupons/{coupon}/deactivate": {
            "post": {
                "operationId": "v1.coupons.deactivate",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/coupons/4b9d3e08-a1f6-4275-9c83-7e01d6a2f594/deactivate \\\n  -H \"Authorization: Bearer sbt_...\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nThe safe way to retire a code: new redemptions stop immediately and every redemption already recorded is kept. A checkout **already in flight** with the code still completes, so expect a late `coupon.redeemed` shortly after. Emits `coupon.deactivated`. Answers `200` with the coupon.",
                "summary": "Deactivate a coupon",
                "tags": [
                    "Coupons"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "coupon",
                        "in": "path",
                        "required": true,
                        "description": "The coupon, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The coupon after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/CouponResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: when the creator has neither the Coupons Addon nor a Growth plan.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-coupon:update"
                ],
                "x-webhook-events": [
                    "coupon.deactivated"
                ],
                "x-mcp-tools": [
                    "deactivate_coupon"
                ]
            }
        },
        "/v1/projects/{project}/creator-tasks": {
            "get": {
                "operationId": "v1.creator-tasks.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/$PROJECT_ID/creator-tasks?status=open\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\n`status` is `open` (the default: tasks not yet done whose grant still stands), `completed`, or `all`. Paged like every list but **oldest first** by default, so the longest-waiting member is at the top.\n\n- `grant_id` is the access ledger row the task belongs to; read it with the [subscription's grants](https://docs.subscriby.net/api/v1/reference/subscriptions/list-a-subscriptions-grants), where its `mode` is `creator_task`.\n- `instructions` is the sentence the dashboard shows the creator, in the creator's locale.\n- `due_at` is null for continuous access and the window's start for a dated pass.\n- `completed_at` and `completed_by_user_id` are set once the task is done.",
                "summary": "List a project's creator tasks",
                "tags": [
                    "Creator Tasks"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "description": "The tab: `open` (the default) lists tasks not yet done whose grant still stands, `completed` the ones marked done, `all` both.",
                        "schema": {
                            "anyOf": [
                                {
                                    "$ref": "#/components/schemas/CreatorTaskFilter"
                                },
                                {
                                    "type": "null"
                                }
                            ]
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `asc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "asc"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page, oldest first by default.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/CreatorTaskResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "9e4b2c71-3d58-4a6f-b0e2-7c1d5f8a9b34",
                                                    "grant_id": "7d1c3e9a-2b64-4f0e-9a58-3c6b1d8e2f47",
                                                    "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                    "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                    "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                    "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                    "resource_title": "Welcome packet",
                                                    "instructions": "Give Ada Lovelace access to Welcome packet.",
                                                    "due_at": null,
                                                    "completed_at": null,
                                                    "completed_by_user_id": null,
                                                    "created_at": "2026-09-12T10:05:30Z"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-mcp-tools": [
                    "list_creator_tasks"
                ]
            }
        },
        "/v1/projects/{project}/creator-tasks/{task}/complete": {
            "post": {
                "operationId": "v1.creator-tasks.complete",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/creator-tasks/$TASK_ID/complete \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nMarks the task done by the token's user, moves the grant to `granted`, and raises `creator_task.completed` followed by `member.resource_added` for the same grant. Answers `200` with the completed task.\n\n> **Nobody messages the member for you.** A manual perk is yours to hand over. Completing the task records that you did and tells your integrations; it does not send the member anything.",
                "summary": "Complete a creator task",
                "tags": [
                    "Creator Tasks"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "task",
                        "in": "path",
                        "required": true,
                        "description": "The task, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the completed task.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/CreatorTaskResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when the task is already done, or its purchase has since ended so there is nothing left to grant; `error.context.task_id` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:update"
                ],
                "x-webhook-events": [
                    "creator_task.completed",
                    "member.resource_added"
                ],
                "x-mcp-tools": [
                    "complete_creator_task"
                ]
            }
        },
        "/v1/projects/{project}/resources/{resource}/standby": {
            "get": {
                "operationId": "v1.recovery.resource-standby.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/projects/$PROJECT_ID/resources/$RESOURCE_ID/standby \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe standby's own identifier on the platform is deliberately absent, as every connector identifier is on the API.",
                "summary": "Get a resource's standby",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "resource",
                        "in": "path",
                        "required": true,
                        "description": "The resource, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the standby.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ResourceStandbyResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                "mirror_enabled": true,
                                                "health_status": "healthy",
                                                "health_status_label": "Healthy",
                                                "health_reason": null,
                                                "health_checked_at": "2026-09-12T02:00:00Z",
                                                "last_mirrored_at": "2026-09-12T01:45:12Z",
                                                "linked_at": "2026-09-01T14:22:09Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: when the resource keeps no standby; `error.context.resource_id` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-mcp-tools": [
                    "get_resource_standby"
                ]
            },
            "patch": {
                "operationId": "v1.recovery.resource-standby.update",
                "description": "```bash\ncurl -X PATCH https://api.subscriby.net/v1/projects/$PROJECT_ID/resources/$RESOURCE_ID/standby \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"mirror\": true}'\n```\n\nSwitches the live mirror on or off: when on, every post made in the channel is copied into the standby as it is made. Only a channel can be mirrored, and switching on needs the Growth plan. Answers `200` with the standby.",
                "summary": "Switch a standby's live mirror",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "resource",
                        "in": "path",
                        "required": true,
                        "description": "The resource, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateResourceStandbyRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "200 with the standby, updated.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ResourceStandbyResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: for a group, a resource without a standby, a plan without the feature, or a caller who is not the project owner.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:update"
                ],
                "x-mcp-tools": [
                    "set_resource_standby_mirror"
                ]
            },
            "delete": {
                "operationId": "v1.recovery.resource-standby.destroy",
                "description": "Stops keeping the standby; the chat itself is untouched. Answers `204` and raises `recovery.standby_removed`.",
                "summary": "Remove a resource's standby",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "resource",
                        "in": "path",
                        "required": true,
                        "description": "The resource, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the caller is not the project owner.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:delete"
                ],
                "x-webhook-events": [
                    "recovery.standby_removed"
                ],
                "x-mcp-tools": [
                    "remove_resource_standby"
                ]
            }
        },
        "/v1/projects/{project}/recovery/settings": {
            "get": {
                "operationId": "v1.recovery.settings.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/projects/$PROJECT_ID/recovery/settings \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\n- `auto_failover_enabled` says whether the platform may swap a banned channel for its standby on its own; `auto_failover_email_consented_at` when the creator accepted the per-email fee a failover may charge for the members the bot cannot reach.\n- `email_delivery` says how members are told after a channel swap the creator ran: `self` (the creator tells them) or `platform` (Subscriby emails them at the fee).\n- `standby_installation_registered` says whether a spare bot is kept; its credentials never appear.",
                "summary": "Get a project's recovery settings",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the settings.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RecoverySettingsResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "auto_failover_enabled": true,
                                                "auto_failover_email_consented_at": "2026-09-01T14:20:00Z",
                                                "email_delivery": "platform",
                                                "email_delivery_label": "Subscriby emails them",
                                                "standby_installation_registered": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-mcp-tools": [
                    "get_recovery_settings"
                ]
            },
            "patch": {
                "operationId": "v1.recovery.settings.update",
                "description": "```bash\ncurl -X PATCH https://api.subscriby.net/v1/projects/$PROJECT_ID/recovery/settings \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"auto_failover\": true, \"accepts_email_fee\": true, \"email_delivery\": \"platform\"}'\n```\n\nEvery field is optional and omitted ones keep their value. Switching `auto_failover` on needs `accepts_email_fee: true` in the same call and the Growth plan. Answers `200` with the settings as they now stand.",
                "summary": "Update a project's recovery settings",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateRecoverySettingsRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "200 with the settings, updated.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RecoverySettingsResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `auto_failover` is switched on without `accepts_email_fee: true` or without the Growth plan, when the caller is not the project owner, or when `email_delivery` is not `self` or `platform`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:update"
                ],
                "x-mcp-tools": [
                    "update_recovery_settings"
                ]
            }
        },
        "/v1/projects/{project}/recovery/members/export": {
            "get": {
                "operationId": "v1.recovery.members.export",
                "description": "```bash\ncurl -L https://api.subscriby.net/v1/projects/$PROJECT_ID/recovery/members/export \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" -o members.csv\n```\n\nThe member list a creator keeps before replacing a bot, as a CSV download (`text/csv`, one member per row: name, email, connector id, active plans, when access ends, resources, whether the bot can still reach them). REST only; there is no MCP tool for a file.",
                "summary": "Export a project's member list",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The CSV, one member per row.",
                        "content": {
                            "text/csv; charset=UTF-8": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            }
                        },
                        "headers": {
                            "Transfer-Encoding": {
                                "required": true,
                                "schema": {
                                    "type": "string",
                                    "enum": [
                                        "chunked"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the caller is not the project owner.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view-any"
                ]
            }
        },
        "/v1/recovery/readiness": {
            "get": {
                "operationId": "v1.recovery.readiness",
                "description": "```bash\ncurl https://api.subscriby.net/v1/recovery/readiness \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe whole checklist the **Readiness** page shows, with its totals.\n\n- `done` is three-valued: `true` or `false` when the platform can verify the line, `null` when it can only remind (`reminder: true`). Reminders never count toward `total`.\n- `locked` says the plan lacks the prevention feature the line needs, so a client shows the upgrade rather than the fix; `prevention` at the top says whether the plan bundles those features at all.\n- `url` is where the line is fixed, or `null` for a reminder. `detail` is the state in words, such as \"2 of 3 projects\".\n- `connector` names the connector a line belongs to (`connector_name` is its display name); both are `null` for the account's own lines.\n\nThe lines are the ones the dashboard lists, in the same order. The account's come first: `second_factor` and `backup_identity`. Then each installed connector's own lines, worded by that connector and keyed within it; Telegram's are `standby_installation`, `standby_spaces`, `auto_failover` and `live_mirror`, one line per key however many projects run it (the detail counts the projects when they differ). Last the two reminders, `off_platform_copy` and `second_admin`. A creator with no connector installed gets the account lines and the reminders alone. Every change to a verifiable line's state raises `recovery.readiness_changed`.",
                "summary": "Get the readiness checklist",
                "tags": [
                    "Disaster Recovery"
                ],
                "responses": {
                    "200": {
                        "description": "200 with the checklist.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RecoveryReadinessResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "prevention": true,
                                                "completed": 4,
                                                "total": 6,
                                                "complete": false,
                                                "items": [
                                                    {
                                                        "key": "second_factor",
                                                        "connector": null,
                                                        "connector_name": null,
                                                        "label": "Two-Factor Authentication or a Passkey",
                                                        "description": "Recovery moves your identity, so the account that runs it should be hard to take over.",
                                                        "icon": "shield-check",
                                                        "prevention": false,
                                                        "reminder": false,
                                                        "done": true,
                                                        "locked": false,
                                                        "detail": "Enabled",
                                                        "url": "https://app.subscriby.net/settings/security"
                                                    },
                                                    {
                                                        "key": "standby_spaces",
                                                        "connector": "telegram",
                                                        "connector_name": "Telegram",
                                                        "label": "A Standby for Every Channel and Group",
                                                        "description": "A spare channel or group the bot already administers, so a banned one is replaced instantly.",
                                                        "icon": "rectangle-stack",
                                                        "prevention": true,
                                                        "reminder": false,
                                                        "done": false,
                                                        "locked": false,
                                                        "detail": "2 of 3 resources",
                                                        "url": "https://app.subscriby.net/recovery/prevention#prevention-projects"
                                                    },
                                                    {
                                                        "key": "off_platform_copy",
                                                        "connector": null,
                                                        "connector_name": null,
                                                        "label": "A Copy of Your Content Outside the Platform",
                                                        "description": "Nothing can be read from a banned space afterwards. Keep your files and posts somewhere the platform cannot take away.",
                                                        "icon": "archive-box",
                                                        "prevention": false,
                                                        "reminder": true,
                                                        "done": null,
                                                        "locked": false,
                                                        "detail": "We cannot check this for you",
                                                        "url": null
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view-any"
                ],
                "x-mcp-tools": [
                    "get_recovery_readiness"
                ]
            }
        },
        "/v1/recovery/incidents": {
            "get": {
                "operationId": "v1.recovery.incidents.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/recovery/incidents?status=open\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nAn incident is one problem a probe detected and has not yet seen fixed: the creator's sign-in account unreachable (`kind: account`), a project's bot refused by the platform (`bot`), or a channel or group the project sells gone or no longer administered (`resources`). It resolves itself when a later probe finds the thing healthy, or is resolved by the recovery that replaced it, which `resolved_by_operation_id` then names.\n\n`status` is `open` (the default: what still needs attention), `resolved`, or `all`. Paginated like every list, newest first by `detected_at`; `sort_by` also accepts `kind`, `status` and `resolved_at`.",
                "summary": "List incidents",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "description": "The tab: `open` (the default, what still needs attention), `resolved`, or `all`.",
                        "schema": {
                            "anyOf": [
                                {
                                    "$ref": "#/components/schemas/RecoveryIncidentFilter"
                                },
                                {
                                    "type": "null"
                                }
                            ]
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `detected_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "detected_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page, newest first by default.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/RecoveryIncidentResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `status` is not `open`, `resolved` or `all`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view-any"
                ],
                "x-mcp-tools": [
                    "list_recovery_incidents"
                ]
            }
        },
        "/v1/recovery/incidents/{incident}": {
            "get": {
                "operationId": "v1.recovery.incidents.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/recovery/incidents/$INCIDENT_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nOne incident.\n\n- `reason` is the connector's own code for what it saw; `reason_label` and `reason_explanation` are that code in the connector's words, the same sentence the alert email carried. Both are `null` when the probe recorded no reason, which is the case for account incidents.\n- `resource_id` and `resource_title` are set on `resources` incidents only; `project_id` is `null` on an account incident.",
                "summary": "Get an incident",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "incident",
                        "in": "path",
                        "required": true,
                        "description": "The incident, resolved within the ledger by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the incident.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RecoveryIncidentResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "6f1e9b27-4c3a-4d58-9e02-b7a1c5d38f64",
                                                "kind": "resources",
                                                "kind_label": "Channels and Groups",
                                                "status": "open",
                                                "status_label": "Open",
                                                "connector": "telegram",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "project_name": "Research Premium",
                                                "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                "resource_title": "Signals",
                                                "reason": "chat_not_found",
                                                "reason_label": "Channel not found",
                                                "reason_explanation": "**Most likely cause:** the platform deleted or banned the channel. Replace it with a new one.",
                                                "detected_at": "2026-09-12T03:19:04Z",
                                                "resolved_at": null,
                                                "resolved_by_operation_id": null
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-mcp-tools": [
                    "get_recovery_incident"
                ]
            }
        },
        "/v1/recovery/operations": {
            "get": {
                "operationId": "v1.recovery.operations.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/recovery/operations?kind=resources&status=completed\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nAn operation is one recovery: run by the creator, by the platform on their behalf (`automatic: true`, the failover you sleep through), or on demand (`on_demand: true`, a Swap & Grant of a healthy resource, which spends no allowance). The row exists from the moment the recovery starts, because it is the quota ledger and the audit trail at once.\n\nBoth filters are optional: `kind` is `account`, `bot` or `resources`; `status` is `started`, `completed`, `failed` or `reverted`. Newest first by `started_at`; `sort_by` also accepts `kind`, `status` and `completed_at`.",
                "summary": "List recovery operations",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "kind",
                        "in": "query",
                        "description": "Narrow to one kind: `account`, `bot` or `resources`. An unknown value is refused.",
                        "schema": {
                            "anyOf": [
                                {
                                    "$ref": "#/components/schemas/RecoveryIssue"
                                },
                                {
                                    "type": "null"
                                }
                            ]
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "description": "Narrow to one status: `started`, `completed`, `failed` or `reverted`. An unknown value is refused.",
                        "schema": {
                            "anyOf": [
                                {
                                    "$ref": "#/components/schemas/RecoveryOperationStatus"
                                },
                                {
                                    "type": "null"
                                }
                            ]
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `started_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "started_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page, newest first by default.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/RecoveryOperationResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `kind` or `status` is not one of its values.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view-any"
                ],
                "x-mcp-tools": [
                    "list_recovery_operations"
                ]
            }
        },
        "/v1/recovery/operations/{operation}": {
            "get": {
                "operationId": "v1.recovery.operations.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/recovery/operations/$OPERATION_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nOne operation, with its undo state.\n\n- `status` is `started` while the recovery runs, then `completed`, `failed` (with `failure_reason`) or `reverted`.\n- `revertible` says whether the creator may still undo it **right now**: it is completed, of a kind that can be undone (an account relink or a channel swap, never a bot replacement), and inside the undo window that `revert_window_ends_at` closes. A client should show the undo exactly when this is `true`.\n- `grant_id` names the support grant that paid for the recovery when the self-service allowance was already spent; `null` otherwise.",
                "summary": "Get a recovery operation",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "operation",
                        "in": "path",
                        "required": true,
                        "description": "The operation, resolved within the ledger by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the operation.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RecoveryOperationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "9a4d2e71-5b38-4c6f-8e12-3d7c9b0a5f21",
                                                "kind": "resources",
                                                "kind_label": "Channels and Groups",
                                                "status": "completed",
                                                "status_label": "Completed",
                                                "connector": "telegram",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "project_name": "Research Premium",
                                                "grant_id": null,
                                                "automatic": true,
                                                "on_demand": false,
                                                "failure_reason": null,
                                                "started_at": "2026-09-12T03:19:10Z",
                                                "completed_at": "2026-09-12T03:19:42Z",
                                                "reverted_at": null,
                                                "revertible": true,
                                                "revert_window_ends_at": "2026-09-13T03:19:42Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-mcp-tools": [
                    "get_recovery_operation"
                ]
            }
        },
        "/v1/recovery/operations/{operation}/roll-call": {
            "get": {
                "operationId": "v1.recovery.operations.roll-call",
                "description": "```bash\ncurl https://api.subscriby.net/v1/recovery/operations/$OPERATION_ID/roll-call \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nWhere the re-admission after a channel recovery stands, read live.\n\n- `total` is how many members the swap set out to re-admit; `regranted` how many hold a fresh link into the new chat; `failed` how many could not be given one.\n- `unreachable` is how many the bot could not message, and `emailed` how many of those were told by email instead (at the per-email fee, when the project opted in).\n- `joined` is stamped the moment the platform approves a member's join request, so `pending` (`regranted − joined`) is who is still outside.\n- `settled` means the queue has handled everyone, so the counters will not move on their own. `can_nudge` is true when somebody is still outside and the reminder cooldown has passed; `cooling_down` and `nudge_available_at` explain a `false`.\n\nA recovery of a kind that re-admits nobody (an account relink, a bot replacement) answers the same shape with every counter at zero rather than an error.",
                "summary": "Get a recovery's roll call",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "operation",
                        "in": "path",
                        "required": true,
                        "description": "The operation, resolved within the ledger by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the counters.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ReadmissionRollCallResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "total": 340,
                                                "regranted": 340,
                                                "failed": 0,
                                                "unreachable": 12,
                                                "emailed": 12,
                                                "joined": 338,
                                                "pending": 2,
                                                "nudged": 1,
                                                "settled": true,
                                                "cooling_down": false,
                                                "can_nudge": true,
                                                "last_nudged_at": "2026-09-12T09:00:00Z",
                                                "nudge_available_at": "2026-09-12T10:00:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-mcp-tools": [
                    "get_recovery_roll_call"
                ]
            }
        },
        "/v1/recovery/allowances": {
            "get": {
                "operationId": "v1.recovery.allowances",
                "description": "```bash\ncurl https://api.subscriby.net/v1/recovery/allowances \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nOne row per kind, plus the window they are counted in.\n\n- `self_service_remaining` is what the rolling window still allows on its own; `grant_remaining` is what support has released on top and not yet spent. `remaining` is their sum and `allowed` whether a recovery of that kind would start right now.\n- `uses_grant` is true when the next recovery would spend a support grant rather than the self-service allowance.\n- `next_self_service_at` is when the self-service allowance returns, `null` while it is available. `last_used_at` is when the kind was last recovered inside the window.\n\nSee [Allowances and support review](https://docs.subscriby.net/disaster-recovery/allowances-and-support-review) for the rule and what support audits before releasing a grant.",
                "summary": "Get the recovery allowances",
                "tags": [
                    "Disaster Recovery"
                ],
                "responses": {
                    "200": {
                        "description": "Array of `RecoveryAllowanceResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "$ref": "#/components/schemas/RecoveryAllowanceResource"
                                            }
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The rule the allowances are counted under.",
                                            "properties": {
                                                "window_days": {
                                                    "type": "integer",
                                                    "description": "The rolling window the allowances are counted in, in days.",
                                                    "examples": [
                                                        90
                                                    ]
                                                },
                                                "self_service_uses": {
                                                    "type": "integer",
                                                    "description": "How many self-service recoveries of each kind the window allows.",
                                                    "examples": [
                                                        1
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "window_days",
                                                "self_service_uses"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "kind": "account",
                                                    "kind_label": "Telegram Account",
                                                    "self_service_remaining": 1,
                                                    "grant_remaining": 0,
                                                    "remaining": 1,
                                                    "allowed": true,
                                                    "uses_grant": false,
                                                    "last_used_at": null,
                                                    "next_self_service_at": null
                                                },
                                                {
                                                    "kind": "bot",
                                                    "kind_label": "Project Bot",
                                                    "self_service_remaining": 1,
                                                    "grant_remaining": 0,
                                                    "remaining": 1,
                                                    "allowed": true,
                                                    "uses_grant": false,
                                                    "last_used_at": null,
                                                    "next_self_service_at": null
                                                },
                                                {
                                                    "kind": "resources",
                                                    "kind_label": "Channels and Groups",
                                                    "self_service_remaining": 0,
                                                    "grant_remaining": 1,
                                                    "remaining": 1,
                                                    "allowed": true,
                                                    "uses_grant": true,
                                                    "last_used_at": "2026-09-12T03:19:10Z",
                                                    "next_self_service_at": "2026-12-11T03:19:10Z"
                                                }
                                            ],
                                            "meta": {
                                                "window_days": 90,
                                                "self_service_uses": 1
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view-any"
                ],
                "x-mcp-tools": [
                    "get_recovery_allowances"
                ]
            }
        },
        "/v1/me/recovery": {
            "get": {
                "operationId": "v1.me.recovery.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/me/recovery \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nRecovering the creator's sign-in account, and keeping a backup account ahead of a ban, are two-sided **handshakes**: the API mints a code, the creator taps the link (or types the code) from the account to detect, the connector records which account that was, and the API confirms. Both sides have to agree, which is what keeps a leaked link from binding a stranger. These endpoints live under `/v1/me` because they are about the caller, never a project, and the actions behind them refuse anyone but the account holder.\n\nThese flows are deliberately not offered as MCP tools: moving a sign-in is a human act, and [`get_me`](https://docs.subscriby.net/mcp/v1/tools/account/get-me) already shows which accounts are linked.\n\n- `primary_display_name` and `backup_display_name` name the accounts as the connector reported them; their identifiers on the connector never appear.\n- `relink_handshake` and `backup_handshake` are the newest handshake of each kind, in whatever state, so a client can pick up a flow the creator started on the dashboard or in the bot.",
                "summary": "Get the caller's recovery account",
                "tags": [
                    "Disaster Recovery"
                ],
                "responses": {
                    "200": {
                        "description": "200 with the summary.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RecoveryAccountResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "primary_display_name": "Ada",
                                                "backup_identity_registered": true,
                                                "backup_display_name": "Backup Ada",
                                                "relink_handshake": null,
                                                "backup_handshake": {
                                                    "id": "0c4f9e2a-7b31-4d68-a5e2-9f1c3b7d6e80",
                                                    "kind": "backup",
                                                    "kind_label": "Backup account",
                                                    "status": "consumed",
                                                    "status_label": "Consumed",
                                                    "code": "K7PM2QXA",
                                                    "start_link": null,
                                                    "connector": "telegram",
                                                    "detected_display_name": "Backup Ada",
                                                    "detected_identity_id": "3c9e1f7a-8b25-4d60-a1f4-7e2c5b9d0a18",
                                                    "expires_at": "2026-09-01T14:35:00Z",
                                                    "completed_at": "2026-09-01T14:22:09Z",
                                                    "created_at": "2026-09-01T14:20:00Z"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ]
            }
        },
        "/v1/me/recovery/handshakes/{handshake}": {
            "get": {
                "operationId": "v1.me.recovery.handshakes.show",
                "description": "`status` moves from `pending` to `completed` when an account taps, with `detected_display_name` and `detected_identity_id` filled; `expired` when the code ran out or was cancelled; `consumed` once confirmed.",
                "summary": "Poll a recovery handshake",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "handshake",
                        "in": "path",
                        "required": true,
                        "description": "The handshake, resolved within the caller's own by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the handshake.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RecoveryHandshakeResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ]
            },
            "delete": {
                "operationId": "v1.me.recovery.handshakes.destroy",
                "description": "Cancels a pending handshake so its code stops working. Answers `204`.",
                "summary": "Cancel a recovery handshake",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "handshake",
                        "in": "path",
                        "required": true,
                        "description": "The handshake, resolved within the caller's own by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the handshake is no longer pending; `error.context.handshake_id` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:delete"
                ]
            }
        },
        "/v1/projects/{project}/resources/{resource}/standby/request": {
            "post": {
                "operationId": "v1.recovery.resource-standby.request",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/resources/$RESOURCE_ID/standby/request \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nAsks the creator, on the connector, to pick the chat that becomes the resource's standby (Growth plan). Answers `202` once the request is sent; the standby appears, announced by `recovery.standby_registered`, the moment they choose.\n\nLinking a standby or a replacement is a conversation with the creator on the connector: the bot messages them with a picker, and the link or the swap happens the moment they choose. The API cannot name the chat directly, because that would take a platform identifier, so it starts the conversation and takes it back. A creator holds one request of each kind at a time, whichever resource it was for.",
                "summary": "Request a standby for a resource",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "resource",
                        "in": "path",
                        "required": true,
                        "description": "The resource, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "202": {
                        "description": "202 with `resource_id` and `status: request_sent`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "resource_id": {
                                                    "type": "string",
                                                    "description": "The resource the standby will be kept for.",
                                                    "examples": [
                                                        "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6"
                                                    ]
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "Always `request_sent`: the creator has been asked on the connector.",
                                                    "const": "request_sent",
                                                    "examples": [
                                                        "request_sent"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "resource_id",
                                                "status"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                "status": "request_sent"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the resource is a perk rather than a place, the creator cannot be reached on the connector, the plan lacks the feature, or the caller is not the project owner; `error.context.resource_id` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:create"
                ],
                "x-mcp-tools": [
                    "request_resource_standby"
                ]
            },
            "delete": {
                "operationId": "v1.recovery.resource-standby.withdraw-request",
                "description": "Takes the open standby request back. A creator holds one request of each kind at a time, whichever resource it was for, so the resource in the path only keys the route. Answers `204`, also when nothing was open.",
                "summary": "Withdraw a standby request",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "resource",
                        "in": "path",
                        "required": true,
                        "description": "The resource, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:delete"
                ],
                "x-mcp-tools": [
                    "withdraw_resource_standby_request"
                ]
            }
        },
        "/v1/projects/{project}/resources/{resource}/standby/use": {
            "post": {
                "operationId": "v1.recovery.resource-standby.use",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/resources/$RESOURCE_ID/standby/use \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nSwaps the resource onto its standby right now: the resource points at the standby chat, the old invite links are revoked, every active member is re-admitted, and the standby is consumed. Answers `200` with the recovery operation the swap ran under (`on_demand: true` when the resource was healthy with no open incident, spending no allowance). Undo is offered for 24 hours through the revert endpoint. Raises `recovery.resource_replaced` and `recovery.standby_removed` with `reason: used`, beside the operation's `recovery.operation_started` and `recovery.operation_completed`.",
                "summary": "Use a resource's standby now",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "resource",
                        "in": "path",
                        "required": true,
                        "description": "The resource, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the recovery operation the swap ran under.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RecoveryOperationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: for a resource without a standby, an allowance already spent for a degraded resource, or a caller who is not the project owner.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:create"
                ],
                "x-webhook-events": [
                    "recovery.operation_started",
                    "recovery.operation_completed",
                    "recovery.resource_replaced",
                    "recovery.standby_removed",
                    "recovery.incident_resolved",
                    "project.resource.updated"
                ],
                "x-mcp-tools": [
                    "use_resource_standby"
                ]
            }
        },
        "/v1/projects/{project}/resources/{resource}/replacement/request": {
            "post": {
                "operationId": "v1.recovery.resource-replacement.request",
                "description": "Asks the creator, on the connector, to pick the chat that replaces the resource's: the same conversation a standby request starts, ending in a swap instead of a spare. For a degraded resource the swap will spend the channel recovery allowance or join the recovery already absorbing swaps; for a healthy one it is on demand and free. Answers `202` once the request is sent.",
                "summary": "Request a replacement for a resource",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "resource",
                        "in": "path",
                        "required": true,
                        "description": "The resource, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "202": {
                        "description": "202 with `resource_id` and `status: request_sent`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "resource_id": {
                                                    "type": "string",
                                                    "description": "The resource whose place will be replaced.",
                                                    "examples": [
                                                        "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6"
                                                    ]
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "Always `request_sent`: the creator has been asked on the connector.",
                                                    "const": "request_sent",
                                                    "examples": [
                                                        "request_sent"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "resource_id",
                                                "status"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                "status": "request_sent"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the resource is a perk with nothing to replace, the creator cannot be reached on the connector, or the caller is not the project owner; `error.context.resource_id` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:create"
                ],
                "x-mcp-tools": [
                    "request_resource_replacement"
                ]
            },
            "delete": {
                "operationId": "v1.recovery.resource-replacement.withdraw-request",
                "description": "Takes the open replacement request back. Answers `204`, also when nothing was open.",
                "summary": "Withdraw a replacement request",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "resource",
                        "in": "path",
                        "required": true,
                        "description": "The resource, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:delete"
                ],
                "x-mcp-tools": [
                    "withdraw_resource_replacement_request"
                ]
            }
        },
        "/v1/projects/{project}/recovery/standby-installation": {
            "delete": {
                "operationId": "v1.recovery.standby-installation.destroy",
                "description": "```bash\ncurl -X DELETE https://api.subscriby.net/v1/projects/$PROJECT_ID/recovery/standby-installation \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nStops keeping the spare bot registered for the project and withdraws it from the connector; the live installation, members and access stay as they are. Answers `204`. Registering one is not offered to tokens, because it takes a credential; the dashboard's Prevention page does that. Raises `recovery.standby_removed` with `standby: installation`.",
                "summary": "Remove a project's standby installation",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the caller is not the project owner.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:delete"
                ],
                "x-webhook-events": [
                    "recovery.standby_removed"
                ],
                "x-mcp-tools": [
                    "remove_standby_installation"
                ]
            }
        },
        "/v1/recovery/operations/{operation}/revert": {
            "post": {
                "operationId": "v1.recovery.operations.revert",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/recovery/operations/$OPERATION_ID/revert \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"resource_id\": \"b73c5f21-9d80-4a6e-8215-4f70ce13a9d6\"}'\n```\n\nInside the undo window (`revert_window_ends_at` on the operation) a completed recovery can be undone. A **channel recovery** is undone one swap at a time: `resource_id` names the resource to put back on its old chat, and every active member is re-admitted there again; the operation reads `reverted` once its last standing swap is undone. An **account relink** is undone whole and takes no `resource_id`: sign-in moves back to the previous account, every browser session is signed out, and a `relink_disputed` incident opens for support. A **bot replacement** cannot be undone.\n\nAnswers `200` with the operation, its `revertible` now `false`. Raises `recovery.operation_reverted`; a channel undo also moves the resource's place (`project.resource.updated` with `changes.space_id`) and an account undo opens the dispute incident (`recovery.incident_opened`).",
                "summary": "Undo a recovery",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "operation",
                        "in": "path",
                        "required": true,
                        "description": "The operation, resolved within the ledger by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/RevertRecoveryOperationRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "200 with the operation, its undo state updated.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RecoveryOperationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: when `resource_id` is not a resource the token manages.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: for a bot replacement, a channel recovery with no `resource_id`, a closed window, a swap already put back, or a recovery that is not the token owner's; `error.context.operation_id` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:update"
                ],
                "x-webhook-events": [
                    "recovery.operation_reverted",
                    "recovery.incident_opened",
                    "project.resource.updated"
                ],
                "x-mcp-tools": [
                    "revert_recovery_operation"
                ]
            }
        },
        "/v1/recovery/operations/{operation}/nudge": {
            "post": {
                "operationId": "v1.recovery.operations.nudge",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/recovery/operations/$OPERATION_ID/nudge \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nSends one reminder, with a fresh link, to every member a channel recovery re-admitted who has not joined the new chat yet, and records the nudge on the operation. Read the roll call first: `can_nudge` says whether anyone is still outside and the cooldown has passed. Answers `200` with the count queued.",
                "summary": "Remind a recovery's stragglers",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "operation",
                        "in": "path",
                        "required": true,
                        "description": "The operation, resolved within the ledger by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with `operation_id` and how many reminders were `nudged`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "operation_id": {
                                                    "type": "string",
                                                    "description": "The recovery whose stragglers were reminded.",
                                                    "examples": [
                                                        "9a4d2e71-5b38-4c6f-8e12-3d7c9b0a5f21"
                                                    ]
                                                },
                                                "nudged": {
                                                    "type": "integer",
                                                    "description": "How many reminders were queued.",
                                                    "examples": [
                                                        2
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "operation_id",
                                                "nudged"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "operation_id": "9a4d2e71-5b38-4c6f-8e12-3d7c9b0a5f21",
                                                "nudged": 2
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when nobody is waiting, the nudge is too soon, or the recovery is of another kind.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:update"
                ],
                "x-mcp-tools": [
                    "nudge_pending_readmissions"
                ]
            }
        },
        "/v1/recovery/operations/{operation}/notify-members": {
            "post": {
                "operationId": "v1.recovery.operations.notify-members",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/recovery/operations/$OPERATION_ID/notify-members \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nAfter a **bot replacement**, emails every member the project can reach by email that its bot changed, with the new bot's link and the portal, at the per-email fee added to the creator's transaction fees. Sent once per recovery: a second call answers with the count already sent and sends nothing. Answers `200` with the count.",
                "summary": "Tell members about a bot replacement",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "operation",
                        "in": "path",
                        "required": true,
                        "description": "The operation, resolved within the ledger by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with `operation_id` and how many members were `notified`, now or earlier.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "operation_id": {
                                                    "type": "string",
                                                    "description": "The recovery the mail concerns.",
                                                    "examples": [
                                                        "9a4d2e71-5b38-4c6f-8e12-3d7c9b0a5f21"
                                                    ]
                                                },
                                                "notified": {
                                                    "type": "integer",
                                                    "description": "How many members were emailed, now or by the earlier call.",
                                                    "examples": [
                                                        327
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "operation_id",
                                                "notified"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "operation_id": "9a4d2e71-5b38-4c6f-8e12-3d7c9b0a5f21",
                                                "notified": 327
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the recovery belongs to no project, so there is nobody to tell; `error.context.operation_id` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:update"
                ],
                "x-mcp-tools": [
                    "notify_members_of_recovery"
                ]
            }
        },
        "/v1/me/recovery/handshakes": {
            "post": {
                "operationId": "v1.me.recovery.handshakes.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/me/recovery/handshakes \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"kind\": \"relink\"}'\n```\n\n`kind` is `relink` (move the sign-in to a new account; needs the account recovery allowance) or `backup` (register a backup account; needs the Growth plan). Answers `201` with the pending handshake: `code` is the eight-character code to type into the bot, `start_link` the link that opens the bot on it (`null` when the creator cannot be reached on the connector), and the handshake expires fifteen minutes after it was minted.",
                "summary": "Open a recovery handshake",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/OpenRecoveryHandshakeRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "201 with the pending handshake, its code and link.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RecoveryHandshakeResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when the account allowance is spent (`relink`), the plan lacks the backup feature (`backup`), `kind` is neither, or the caller is not the account holder.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:create"
                ]
            }
        },
        "/v1/me/recovery/handshakes/{handshake}/confirm": {
            "post": {
                "operationId": "v1.me.recovery.handshakes.confirm",
                "description": "Confirms a **completed relink**: the sign-in moves to the account that tapped, every browser session is signed out, the account allowance is spent, and the undo mail goes out. Answers `200` with the recovery operation (`kind: account`, `revertible: true`) and raises `recovery.identity_relinked` beside the operation's `recovery.operation_started` and `recovery.operation_completed`.",
                "summary": "Confirm a relink handshake",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "handshake",
                        "in": "path",
                        "required": true,
                        "description": "The handshake, resolved within the caller's own by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the recovery operation.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RecoveryOperationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: for a pending or expired handshake, a `backup` handshake (which is confirmed by registering the backup identity), or a caller who is not the account holder; `error.context.handshake_id` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:create"
                ],
                "x-webhook-events": [
                    "recovery.operation_started",
                    "recovery.operation_completed",
                    "recovery.identity_relinked",
                    "recovery.incident_resolved"
                ]
            }
        },
        "/v1/me/recovery/backup-identity": {
            "post": {
                "operationId": "v1.me.recovery.backup-identity.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/me/recovery/backup-identity \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"handshake_id\": \"0c4f9e2a-7b31-4d68-a5e2-9f1c3b7d6e80\"}'\n```\n\nRegisters the account a **completed backup** handshake detected as the backup (Growth plan). Answers `200` with the account summary.",
                "summary": "Register a backup account",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/RegisterBackupIdentityRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "200 with the account summary.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RecoveryAccountResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: when the handshake is not one of the caller's; `error.context.handshake_id` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when the handshake is not a completed `backup` handshake, the plan lacks the feature, or the caller is not the account holder.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:create"
                ]
            },
            "delete": {
                "operationId": "v1.me.recovery.backup-identity.destroy",
                "description": "Stops keeping a backup. Answers `204`.",
                "summary": "Remove the backup account",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the caller is not the account holder.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:delete"
                ]
            }
        },
        "/v1/me/recovery/backup-identity/switch": {
            "post": {
                "operationId": "v1.me.recovery.backup-identity.switch",
                "description": "Moves the sign-in to the backup right now, keeping the previous account as the new backup; spends the account allowance and offers the same undo as a relink. Answers `200` with the recovery operation and raises `recovery.identity_relinked` beside the operation's `recovery.operation_started` and `recovery.operation_completed`.",
                "summary": "Switch to the backup account",
                "tags": [
                    "Disaster Recovery"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the recovery operation.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RecoveryOperationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when no backup is registered, the account allowance is spent, or the caller is not the account holder.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-recovery:create"
                ],
                "x-webhook-events": [
                    "recovery.operation_started",
                    "recovery.operation_completed",
                    "recovery.identity_relinked",
                    "recovery.incident_resolved"
                ]
            }
        },
        "/v1/projects/{project}/distribution/deep-link": {
            "get": {
                "operationId": "v1.distribution.deep-link",
                "description": "Builds a start link against the project's connected installation. The payload depends on which query parameter you pass (at most one; an access code wins over a plan, and a plan over a custom parameter):\n\n| Query parameter | Resulting payload           | Acted on by the bot?                                         |\n| --------------- | --------------------------- | ------------------------------------------------------------ |\n| `access_code`   | the code verbatim           | Yes: redeemed on open.                                       |\n| `plan_id`       | the plan's bare UUID        | Yes: opens that plan's checkout flow.                        |\n| `custom`        | the caller-supplied string  | No, see below.                                               |\n| *(none)*        | `project_<uuid>`            | No: falls through to the project home, which is the intent.  |\n\n> **Only a bare UUID is acted on.** The bot acts on a start payload only when it is a bare UUID: it is matched against the project's plans first, then tried as an access code. `custom` payloads and the default `project_<uuid>` do not match that shape, so the bot ignores them and opens its home screen. `custom` is therefore a passthrough for **your own** tracking: the platform delivers it and you can read it off the update in a webhook consumer, but Subscriby neither stores it nor attaches it to the member.\n\n```bash\ncurl \"https://api.subscriby.net/v1/projects/$PROJECT_ID/distribution/deep-link?plan_id=$PLAN_ID\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```",
                "summary": "Build a deep link",
                "tags": [
                    "Distribution"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "plan_id",
                        "in": "query",
                        "description": "A plan of this project; the link then opens that plan's checkout. Answers 404 for a plan outside the project. Ignored when `access_code` is also sent.",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "access_code",
                        "in": "query",
                        "description": "An access code, carried verbatim and redeemed when the link is opened. Wins over `plan_id` and `custom`.",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "maxLength": 64
                        }
                    },
                    {
                        "name": "custom",
                        "in": "query",
                        "description": "Your own tracking string, 1 to 64 characters of letters, digits, underscore or hyphen. Delivered by the platform but not acted on or stored by Subscriby. Used only when neither `access_code` nor `plan_id` is sent.",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "pattern": "^[A-Za-z0-9_-]{1,64}$"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The bot URL, the start payload and the assembled deep link.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "project_id": {
                                                    "type": "string",
                                                    "description": "The project.",
                                                    "examples": [
                                                        "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                                    ]
                                                },
                                                "bot_url": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The public URL of the project's live installation.",
                                                    "examples": [
                                                        "https://example.org/research_bot"
                                                    ]
                                                },
                                                "start_payload": {
                                                    "type": "string",
                                                    "description": "The payload the link carries, as the table above resolves it.",
                                                    "examples": [
                                                        "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d"
                                                    ]
                                                },
                                                "deep_link": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The assembled start link.",
                                                    "examples": [
                                                        "https://example.org/research_bot?start=a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "project_id",
                                                "bot_url",
                                                "start_payload",
                                                "deep_link"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "bot_url": "https://example.org/research_bot",
                                                "start_payload": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
                                                "deep_link": "https://example.org/research_bot?start=a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: when `plan_id` does not belong to this project.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: with `reason: no_bot_attached` when the project has no connected installation to link to. `VALIDATION_FAILED`: on `plan_id` when it is not a UUID, or on `custom` when it is not 1 to 64 characters of letters, digits, underscore or hyphen.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "distribution:read"
                ],
                "x-mcp-tools": [
                    "get_deep_link"
                ]
            }
        },
        "/v1/projects/{project}/distribution/portal-url": {
            "get": {
                "operationId": "v1.distribution.portal-url",
                "description": "The portal URL always uses the project's current `handle`. If you change the handle the portal URL updates in lock-step; any old link answers 404 on the portal host.",
                "summary": "Get the portal URL",
                "tags": [
                    "Distribution"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The portal URL for the project's handle.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "project_id": {
                                                    "type": "string",
                                                    "description": "The project.",
                                                    "examples": [
                                                        "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                                    ]
                                                },
                                                "handle": {
                                                    "type": "string",
                                                    "description": "The project's current handle, the last segment of the portal URL.",
                                                    "examples": [
                                                        "research-premium"
                                                    ]
                                                },
                                                "portal_url": {
                                                    "type": "string",
                                                    "description": "The subscriber portal for the project.",
                                                    "examples": [
                                                        "https://my.subscriby.net/research-premium"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "project_id",
                                                "handle",
                                                "portal_url"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "handle": "research-premium",
                                                "portal_url": "https://my.subscriby.net/research-premium"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "distribution:read"
                ],
                "x-mcp-tools": [
                    "get_portal_url"
                ]
            }
        },
        "/v1/groups": {
            "get": {
                "operationId": "v1.groups.index",
                "description": "```bash\ncurl https://api.subscriby.net/v1/groups \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nEvery group across the teams the caller sees, newest first. Rows carry neither `permissions` nor `member_ids`; read a group individually for those. Visibility is the union of every team the caller owns or belongs to; a group from a team the caller cannot see answers `404 RESOURCE_NOT_FOUND` rather than `403`, so the API cannot be used to discover that a group id exists.",
                "summary": "List groups",
                "tags": [
                    "Groups"
                ],
                "parameters": [
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Groups across every team the caller belongs to.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/GroupResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "group:view-any"
                ],
                "x-mcp-tools": [
                    "list_groups"
                ]
            },
            "post": {
                "operationId": "v1.groups.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/groups \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n        \"team_id\": \"a83f0d51-4c92-4b7e-8615-2fd9e70a3c86\",\n        \"code\": \"billing-team\",\n        \"name\": \"Billing Team\",\n        \"permissions\": [\"project-subscription:view-any\"]\n      }'\n```\n\n> **Choose the code deliberately.** `code` is unique within the team and **cannot be changed afterwards**: permissions are addressed by it. Only `name` and the permission set are mutable.\n\nA group starts empty. Add people with the members endpoint; membership is deliberately not a field here, because replacing who is in a group and naming it are different operations with different consequences.\n\nAnswers `201` with the group and its permissions. Emits `group.created`.",
                "summary": "Create a group",
                "tags": [
                    "Groups"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreGroupRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The group resource as a 201.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/GroupResource"
                                                },
                                                {
                                                    "type": "object",
                                                    "required": [
                                                        "permissions"
                                                    ]
                                                }
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: below the Growth tier; nothing changes.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: when `team_id` is not one of the caller's teams.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when a group with that code already exists in the team; `error.context.code` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "group:create"
                ],
                "x-webhook-events": [
                    "group.created"
                ],
                "x-mcp-tools": [
                    "create_group"
                ]
            }
        },
        "/v1/groups/{group}": {
            "get": {
                "operationId": "v1.groups.show",
                "description": "One group with its `permissions` and `member_ids`, which are returned when the group is read individually or after a write and omitted from list responses so a listing stays one query.",
                "summary": "Get a group",
                "tags": [
                    "Groups"
                ],
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "description": "The group, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The group resource.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/GroupResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "1f68d92a-04c5-4e83-97b1-3d6a05e2f847",
                                                "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                                "code": "ops",
                                                "name": "Ops",
                                                "permissions": [
                                                    "project:view-any",
                                                    "project-user:view-any"
                                                ],
                                                "member_ids": [
                                                    "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                    "4b8e2f6a-1c3d-4e5f-9a7b-8c9d0e1f2a3b"
                                                ],
                                                "created_at": "2026-05-18T10:05:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "group:view"
                ],
                "x-mcp-tools": [
                    "get_group"
                ]
            },
            "patch": {
                "operationId": "v1.groups.update",
                "description": "```bash\ncurl -X PATCH https://api.subscriby.net/v1/groups/$GROUP_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\": \"Billing & Finance\"}'\n```\n\n> **Permissions replace, they do not merge.** Sending `permissions` sets the group's permissions to exactly that list. **Omit the key entirely** to leave the existing set untouched while changing only the name.\n\n`code` and `team_id` are prohibited: a group is neither renamed by code nor moved between teams. Answers `200` with the group and its permissions. Emits `group.updated`.",
                "summary": "Update a group",
                "tags": [
                    "Groups"
                ],
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "description": "The group, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreGroupRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The updated group resource.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/GroupResource"
                                                },
                                                {
                                                    "type": "object",
                                                    "required": [
                                                        "permissions"
                                                    ]
                                                }
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: below the Growth tier; nothing changes.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `code` or `team_id` is sent, or a permission code is unknown.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "group:update"
                ],
                "x-webhook-events": [
                    "group.updated"
                ],
                "x-mcp-tools": [
                    "update_group"
                ]
            },
            "delete": {
                "operationId": "v1.groups.destroy",
                "description": "```bash\ncurl -X DELETE https://api.subscriby.net/v1/groups/$GROUP_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nReturns `204 No Content`. Everyone in the group loses whatever it granted them, but stays in the team. Not gated by tier. Emits `group.deleted`.",
                "summary": "Delete a group",
                "tags": [
                    "Groups"
                ],
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "description": "The group, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "group:delete"
                ],
                "x-webhook-events": [
                    "group.deleted"
                ],
                "x-mcp-tools": [
                    "delete_group"
                ]
            }
        },
        "/v1/groups/{group}/members": {
            "put": {
                "operationId": "v1.groups.sync-members",
                "description": "```bash\ncurl -X PUT https://api.subscriby.net/v1/groups/$GROUP_ID/members \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"user_ids\": [\"2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80\", \"4b8e2f6a-1c3d-4e5f-9a7b-8c9d0e1f2a3b\"]}'\n```\n\nThis is a **sync**, not an add. The array replaces the membership entirely: anyone omitted is removed, and `[]` empties the group. That is deliberate and differs from the permission field above: clearing a group is a legitimate thing to ask for, whereas silently stripping every permission because a field was blank is not.\n\nThis is the one write in the identity surface whose tier gate depends on its argument: a sync that only removes people succeeds on any tier, and one that adds anybody needs Growth. Deciding from the route alone would leave a lapsed creator unable to take one person out of a group without deleting the whole group, and deleting is not gated, so the gate would only be pushing them toward the more destructive option.\n\nEvery id must already belong to the group's team. A group grants permissions inside one tenant, so an outsider is refused naming the offending ids; the whole call fails rather than partly applying, so you never end up with a membership you did not ask for.\n\nAnswers `200` with the group, its `permissions` and its `member_ids`. Emits `group.members_synced`, which carries `added_ids` and `removed_ids` as well as the final list, so an access-control mirror does not have to diff two snapshots to work out what moved. A sync that changes nothing emits nothing.",
                "summary": "Replace a group's members",
                "tags": [
                    "Groups"
                ],
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "description": "The group, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/SyncGroupMembersRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The group with its permissions and members.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/GroupResource"
                                                },
                                                {
                                                    "type": "object",
                                                    "required": [
                                                        "permissions",
                                                        "member_ids"
                                                    ]
                                                }
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: below the Growth tier when the sync would add somebody; a sync that only removes people succeeds on any tier.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when any id is not a member of the group's team; `error.context.user_ids` lists the outsiders.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "group:update"
                ],
                "x-webhook-events": [
                    "group.members_synced"
                ],
                "x-mcp-tools": [
                    "sync_group_members"
                ]
            }
        },
        "/v1/me/identities": {
            "get": {
                "operationId": "v1.me.identities.index",
                "description": "```bash\ncurl https://api.subscriby.net/v1/me/identities \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nEvery account linked to the caller's creator account, by connector then purpose. Never paginated.\n\n- `purpose` is `primary` (the account that signs you in and receives alerts) or `backup` (the account registered for [Disaster Recovery](https://docs.subscriby.net/account/account-recovery)).\n- `source` says how the link was proven: `handshake` (you completed a link from Settings), `bot` (the account came in through the connector's own flow), `backfill` (migrated from before connectors), `portal` or `adopted`.\n- `external_id` is the platform's own id for the account, `username` its handle when the platform has one. Secrets and chat rows are never returned.\n\n> **Linking has no endpoint.** Linking is a two-sided proof: you open it from **Settings → Security → Linked accounts** and finish it from the account itself, by opening the link or sending the code to the connector's bot. A token cannot stand in for a person on the connector, so there is nothing to POST here.",
                "summary": "List the caller's linked accounts",
                "tags": [
                    "Identities"
                ],
                "responses": {
                    "200": {
                        "description": "Array of `UserIdentityResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "$ref": "#/components/schemas/UserIdentityResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "0c2d8a7e-4b1f-4d3e-9a6b-2f5e8c1d7a90",
                                                    "connector": "telegram",
                                                    "purpose": "primary",
                                                    "source": "handshake",
                                                    "external_id": "123456789",
                                                    "display_name": "Ada Lovelace",
                                                    "username": "ada",
                                                    "linked_at": "2026-09-12T10:05:00Z",
                                                    "verified_at": "2026-09-12T10:05:00Z"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-mcp-tools": [
                    "get_me"
                ]
            }
        },
        "/v1/me/identities/{identity}": {
            "delete": {
                "operationId": "v1.me.identities.destroy",
                "description": "```bash\ncurl -X DELETE https://api.subscriby.net/v1/me/identities/$IDENTITY_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nDrops a **primary** link at once and answers an empty `204`. You keep your password and passkeys, so nothing locks you out; what you lose until you link again is the connector side: its bot can no longer reach you or manage your projects, and its sign-in button no longer signs you in.",
                "summary": "Unlink an account",
                "tags": [
                    "Identities"
                ],
                "parameters": [
                    {
                        "name": "identity",
                        "in": "path",
                        "required": true,
                        "description": "One of the caller's links, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: for an id that is not one of the caller's own links, so the API cannot be used to probe which ids exist.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: for a **backup** account: it is removed from the Disaster Recovery page, where the change is recorded, not from here.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:write"
                ]
            }
        },
        "/v1/projects/{project}/knowledge": {
            "get": {
                "operationId": "v1.knowledge.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/knowledge?per_page=50\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nPages the entries, newest first. Each row names the entry's `kind`, its `audience`, its `status` with a label beside each, its title and how many passages it became; `body` is `null` on every row. Sort with `sort_by` (`created_at` by default, or `updated_at`, `title`) and `sort_direction`.",
                "summary": "List a project's Knowledge",
                "tags": [
                    "Knowledge"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page of entries, without their text.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/KnowledgeEntryResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL.",
                                                    "examples": [
                                                        "…"
                                                    ]
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL.",
                                                    "examples": [
                                                        "…"
                                                    ]
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page.",
                                                    "examples": [
                                                        null
                                                    ]
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page.",
                                                    "examples": [
                                                        null
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs.",
                                                    "examples": [
                                                        "…"
                                                    ]
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "examples": [
                                                        50
                                                    ],
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "3b7e4d2a-9c1f-4a6b-8d5e-2f7c9a1b3e4d",
                                                    "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                    "kind": "question",
                                                    "kind_label": "Question & Answer",
                                                    "audience": "members",
                                                    "audience_label": "Members & Team",
                                                    "status": "ready",
                                                    "status_label": "Ready",
                                                    "title": "When does my membership renew?",
                                                    "body": null,
                                                    "file_name": null,
                                                    "file_size": null,
                                                    "mime": null,
                                                    "chunk_count": 1,
                                                    "characters": 64,
                                                    "failure": null,
                                                    "indexed_at": "2026-10-19T16:02:11+00:00",
                                                    "created_at": "2026-10-19T16:02:11+00:00",
                                                    "updated_at": "2026-10-19T16:02:11+00:00"
                                                }
                                            ],
                                            "links": {
                                                "first": "…",
                                                "last": "…",
                                                "prev": null,
                                                "next": null
                                            },
                                            "meta": {
                                                "current_page": 1,
                                                "from": 1,
                                                "last_page": 1,
                                                "path": "…",
                                                "per_page": 50,
                                                "to": 1,
                                                "total": 1
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-knowledge:view-any"
                ],
                "x-mcp-tools": [
                    "list_knowledge_entries"
                ]
            },
            "post": {
                "operationId": "v1.knowledge.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/knowledge \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"kind\": \"document\",\n    \"title\": \"House rules\",\n    \"body\": \"# House rules\\n\\nClasses start on the hour. Arrive five minutes early…\",\n    \"audience\": \"members\"\n  }'\n```\n\nAnswers `201` with the entry, its `body` included, already cut into passages and in the index: a member can be answered from it the moment this returns. `kind` is fixed once the entry exists; a guide that should have been a question is a new entry. `audience` defaults to `members`, because most of what a creator writes down is written for members; `team` keeps it to the creator's own surfaces.",
                "summary": "Create a Knowledge entry",
                "tags": [
                    "Knowledge"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreKnowledgeEntryRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The entry with its text.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/KnowledgeEntryResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TOKEN_MISSING_ABILITY`: when the token lacks `project-knowledge:create`, or its owner's role on the project's team may not add Knowledge.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `kind` is not `question` or `document`, `title` is outside 2 to 160 characters, `body` is outside 2 to 50,000 characters, `audience` is not `members` or `team`, or the project already holds 200 entries.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-knowledge:create"
                ],
                "x-webhook-events": [
                    "knowledge.created"
                ],
                "x-mcp-tools": [
                    "create_knowledge_entry"
                ]
            }
        },
        "/v1/projects/{project}/knowledge/{entry}": {
            "get": {
                "operationId": "v1.knowledge.show",
                "description": "The entry with its `body`: the answer, or the document's text as it was read out of the file or sent in, headings included for a Markdown document. `status` is `ready` once the passages are in the index, `indexing` while they are cut, `failed` when the text could not be read, in which case `failure` says why.",
                "summary": "Get a Knowledge entry",
                "tags": [
                    "Knowledge"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "entry",
                        "in": "path",
                        "required": true,
                        "description": "The entry, resolved within the project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The entry with its text.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/KnowledgeEntryResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "3b7e4d2a-9c1f-4a6b-8d5e-2f7c9a1b3e4d",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "kind": "question",
                                                "kind_label": "Question & Answer",
                                                "audience": "members",
                                                "audience_label": "Members & Team",
                                                "status": "ready",
                                                "status_label": "Ready",
                                                "title": "When does my membership renew?",
                                                "body": "Memberships renew on the first day of every month, at the price you joined on.",
                                                "file_name": null,
                                                "file_size": null,
                                                "mime": null,
                                                "chunk_count": 1,
                                                "characters": 64,
                                                "failure": null,
                                                "indexed_at": "2026-10-19T16:02:11+00:00",
                                                "created_at": "2026-10-19T16:02:11+00:00",
                                                "updated_at": "2026-10-19T16:02:11+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-knowledge:view"
                ],
                "x-mcp-tools": [
                    "get_knowledge_entry"
                ]
            },
            "patch": {
                "operationId": "v1.knowledge.update",
                "description": "```bash\ncurl -X PATCH https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/knowledge/3b7e4d2a-9c1f-4a6b-8d5e-2f7c9a1b3e4d \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"audience\": \"team\" }'\n```\n\nAnswers `200` with the complete entry after the change. **Every field is optional and an omitted one keeps its stored value**, so the request above changes who may be answered from the entry and nothing else. New words in `title` or `body` are cut into passages again in the same step, and the old passages go with them, so the Copilot never reads a mix of old and new; a new `audience` alone retags the passages without rewriting them.",
                "summary": "Update a Knowledge entry",
                "tags": [
                    "Knowledge"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "entry",
                        "in": "path",
                        "required": true,
                        "description": "The entry, resolved within the project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateKnowledgeEntryRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The entry with its text, updated.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/KnowledgeEntryResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TOKEN_MISSING_ABILITY`: when the token lacks `project-knowledge:update`, or its owner's role on the project's team may not change Knowledge.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when a field sent is outside its bounds.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-knowledge:update"
                ],
                "x-webhook-events": [
                    "knowledge.updated"
                ],
                "x-mcp-tools": [
                    "update_knowledge_entry"
                ]
            },
            "delete": {
                "operationId": "v1.knowledge.destroy",
                "description": "Answers `204`. The entry, its passages and its file go in one step, so the Copilot stops answering from it at once. A second `DELETE` of the same id is `404 RESOURCE_NOT_FOUND`; a token whose owner's role may not remove Knowledge is `403 TOKEN_MISSING_ABILITY`.",
                "summary": "Delete a Knowledge entry",
                "tags": [
                    "Knowledge"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "entry",
                        "in": "path",
                        "required": true,
                        "description": "The entry, resolved within the project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-knowledge:delete"
                ],
                "x-webhook-events": [
                    "knowledge.deleted"
                ],
                "x-mcp-tools": [
                    "delete_knowledge_entry"
                ]
            }
        },
        "/v1/me": {
            "get": {
                "operationId": "v1.me.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/me \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe caller's account; never paginated.\n\n> **Read it once per session.** Nothing here changes under a running client except by an action the client itself takes (linking an account, changing alert destinations, switching plan). Read it on sign-in and after those actions; there is no need to poll it.\n\n- `plan` is the platform tier's type (`free`, `starter`, `growth`, …) while the subscription is active, or `null` without one. It is the plan that gates what you can do, not the one still being billed while past due.\n- `capabilities` lists every capability the tiers can grant, each `true` when your plan or an active add-on grants it. The set is fixed by the platform, so a client can render toggles from the keys without knowing them in advance.\n- `current_team` is the team the token is scoped to (`scope:team:<uuid>`), when you still belong to it; `null` when the token carries no team scope. Its `id` is the value every project call resolves against.\n- `teams` is every team you own or are a member of, the same list as [`GET /v1/teams`](https://docs.subscriby.net/api/v1/reference/teams/list-teams).\n- `identities` is the same list as [`GET /v1/me/identities`](https://docs.subscriby.net/api/v1/reference/identities).\n- `alert_destinations` is the same list as [`GET /v1/me/alert-destinations`](https://docs.subscriby.net/api/v1/reference/alert-destinations); `alert_destinations_default` is `true` while no destination has been written and the default routing applies (every class to your primary connected account, critical classes by email).\n- `unread_notifications` is how many entries of your [Notifications Center](https://docs.subscriby.net/api/v1/reference/notifications) you have not opened, the number on the sidebar entry.\n- `partner_code` and `partner_link` are your [Partner Program](https://docs.subscriby.net/api/v1/reference/partner-program) code and the web link it rides on, once Subscriby approved you as a partner; `null` before. The full standing, the referrals, the ledger and the payouts are at `GET /v1/me/partner`.",
                "summary": "Get the caller's account",
                "tags": [
                    "Me"
                ],
                "responses": {
                    "200": {
                        "description": "The caller's account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/MeResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "name": "Ada Lovelace",
                                                "email": "ada@example.com",
                                                "locale": "en",
                                                "email_verified": true,
                                                "plan": "growth",
                                                "capabilities": {
                                                    "no_branding": true,
                                                    "time_limited_passes": true,
                                                    "coupons": true,
                                                    "free_plans": true,
                                                    "teams": true,
                                                    "disaster_recovery_prevention": true,
                                                    "multi_connector": true
                                                },
                                                "current_team": {
                                                    "id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                                    "name": "Analytical Engines",
                                                    "owner_user_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                    "personal": true,
                                                    "created_at": "2026-05-18T10:05:00Z"
                                                },
                                                "teams": [
                                                    {
                                                        "id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                                        "name": "Analytical Engines",
                                                        "owner_user_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                        "personal": true,
                                                        "created_at": "2026-05-18T10:05:00Z"
                                                    }
                                                ],
                                                "identities": [
                                                    {
                                                        "id": "0c2d8a7e-4b1f-4d3e-9a6b-2f5e8c1d7a90",
                                                        "connector": "telegram",
                                                        "purpose": "primary",
                                                        "source": "handshake",
                                                        "external_id": "123456789",
                                                        "display_name": "Ada Lovelace",
                                                        "username": "ada",
                                                        "linked_at": "2026-09-12T10:05:00Z",
                                                        "verified_at": "2026-09-12T10:05:00Z"
                                                    }
                                                ],
                                                "alert_destinations": [],
                                                "alert_destinations_default": true,
                                                "unread_notifications": 3,
                                                "partner_code": "ADA7Q2X",
                                                "partner_link": "https://app.subscriby.net/r/ADA7Q2X",
                                                "created_at": "2026-05-18T10:05:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-mcp-tools": [
                    "get_me"
                ]
            }
        },
        "/v1/me/export": {
            "get": {
                "operationId": "v1.me.export.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/me/export -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe caller's most recent export, whatever its state; `404 RESOURCE_NOT_FOUND` when none was ever requested. Poll it after a `POST` until `status` is `ready`, then download the zip from `download_url`, a signed link that works until `download_url_expires_at`; every read of a ready export mints a fresh link. The archive itself is removed at `expires_at`, after which `status` reads `expired` and a new export must be requested.\n\n- `status` is `queued`, `building`, `ready`, `failed` or `expired`; only `ready` carries `download_url`.\n- `reason` is `manual` for a request from Settings or this endpoint, `deletion` for the archive a scheduled account deletion builds on its own.",
                "summary": "Read the latest export",
                "tags": [
                    "Me"
                ],
                "responses": {
                    "200": {
                        "description": "The export.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/AccountExportResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "4f2a7c1e-9b3d-4e8a-a6c5-1d2e3f4a5b6c",
                                                "status": "ready",
                                                "reason": "manual",
                                                "requested_at": "2026-10-07T09:12:00Z",
                                                "completed_at": "2026-10-07T09:14:21Z",
                                                "expires_at": "2026-10-14T09:14:21Z",
                                                "size_bytes": 184320,
                                                "projects_count": 2,
                                                "download_url": "https://app.subscriby.net/account/exports/4f2a7c1e-9b3d-4e8a-a6c5-1d2e3f4a5b6c/download?expires=1760000000&signature=0f3c…",
                                                "download_url_expires_at": "2026-10-08T09:30:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:export"
                ],
                "x-mcp-tools": [
                    "get_account_export"
                ]
            },
            "post": {
                "operationId": "v1.me.export.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/me/export -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" -H \"Idempotency-Key: 7c1b2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e\"\n```\n\nQueues an archive of everything the caller's account holds: the account as `GET /v1/me` describes it, the webhook endpoints (never their signing secrets), the platform subscription with its invoices, and for every project the plans, resources, payment methods (never their keys), members, subscriptions, payments, coupons, dated windows and support conversations, each as a JSON file in the shape this API publishes, plus one workbook per project with a sheet per table. Answers `202` with the queued export. The build runs in the background and takes from seconds to a few minutes; the creator is also emailed a signed link when it is ready.\n\nOne export may be in flight per account and one may be requested a day; a second request is `422 VALIDATION_FAILED` with the reason and, for the daily limit, when the next one is allowed. Read the existing export instead.\n\n> **The archive holds the members' personal data.** Hand the link only to the creator who owns the token, and treat the file as you would their database.",
                "summary": "Ask for an account export",
                "tags": [
                    "Me"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "202": {
                        "description": "202 with the queued export.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/AccountExportResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "4f2a7c1e-9b3d-4e8a-a6c5-1d2e3f4a5b6c",
                                                "status": "queued",
                                                "reason": "manual",
                                                "requested_at": "2026-10-07T09:12:00Z",
                                                "completed_at": null,
                                                "expires_at": null,
                                                "size_bytes": null,
                                                "projects_count": null,
                                                "download_url": null,
                                                "download_url_expires_at": null
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:export"
                ],
                "x-mcp-tools": [
                    "request_account_export"
                ]
            }
        },
        "/v1/projects/{project}/members": {
            "get": {
                "operationId": "v1.members.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/$PROJECT_ID/members?status=customer\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nNewest first, paged with `page` and `per_page` (default 25; `limit` is accepted as an alias). `status` narrows to one lifecycle state. `identity` looks one member up by the account they connected, `connector:external_id`, for a workflow that starts from a platform event and needs the member behind an account id; the page then holds that one member with their `identities` embedded, or no rows.",
                "summary": "List a project's members",
                "tags": [
                    "Members"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "description": "Narrow the page to one lifecycle state: `lead`, `trialing`, `customer`, `churned` or `banned`. Any other value is refused rather than answered with an empty page, so a typo in an automation is noticed.",
                        "schema": {
                            "anyOf": [
                                {
                                    "$ref": "#/components/schemas/ProjectUserStatus"
                                },
                                {
                                    "type": "null"
                                }
                            ]
                        }
                    },
                    {
                        "name": "identity",
                        "in": "query",
                        "description": "Find the member who connected a given account: the connector key and the platform's own id for the account joined by a colon, `connector:123456789`. The page then holds that one member with their `identities` embedded, or no rows when nobody in the project connected that account. A value with no connector before the colon is refused.",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "pattern": "^[a-z0-9][a-z0-9-]*:\\S+$",
                            "maxLength": 255
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page, newest first; one row or none when narrowed to an account, with its connected accounts embedded.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/MemberResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `status` is not one of the five states, or `identity` has no connector before the colon.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-user:view-any"
                ],
                "x-mcp-tools": [
                    "find_member_by_identity",
                    "list_subscribers"
                ]
            }
        },
        "/v1/projects/{project}/members/{member}": {
            "get": {
                "operationId": "v1.members.show",
                "description": "One member with their connected accounts embedded as `identities`.\n\n`email` and `billing_email` are present only when the calling token carries `project-user:view`, which this route requires; a roster-only token (`project-user:view-any`) never sees them on the list, where the keys are absent, not null. The two are not interchangeable:\n\n| Field           | Where it comes from                                                                                       | Safe to contact?             |\n| --------------- | --------------------------------------------------------------------------------------------------------- | ---------------------------- |\n| `email`         | The member chose it themselves and verified it. It is their portal sign-in credential.                    | Yes                          |\n| `billing_email` | Whatever address they gave a payment provider at checkout. Never verified, never used for authentication. | Treat as identification only |\n\nMembers join through a bot and are never asked for an email, so for most of them `email` is `null` and `billing_email` is the only address on record, which is what makes it useful for matching a refund request to a subscription.\n\n`billing_email` is populated automatically from the payment provider on every new payment (Stripe, PayPal, Paystack, Razorpay and Skrill). Members who last paid before that capture existed may have `null` until their next payment, and members who joined by redeeming an access code never had a payment at all, so they have no billing address to record.",
                "summary": "Get a member",
                "tags": [
                    "Members"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "member",
                        "in": "path",
                        "required": true,
                        "description": "The member, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The member.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/MemberResource"
                                                },
                                                {
                                                    "type": "object",
                                                    "required": [
                                                        "identities",
                                                        "source"
                                                    ]
                                                }
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "username": "@janedoe",
                                                "first_name": "Jane",
                                                "last_name": "Doe",
                                                "email": null,
                                                "billing_email": "jane@example.com",
                                                "status": "customer",
                                                "joined_at": "2026-05-18T10:05:00Z",
                                                "created_at": "2026-05-18T10:05:00Z",
                                                "updated_at": "2026-05-18T10:05:00Z",
                                                "identities": [
                                                    {
                                                        "id": "6a1f0c3e-2d4b-4e8a-9c7d-1b5e3f9a2c4d",
                                                        "connector": "telegram",
                                                        "source": "handshake",
                                                        "preferred": true,
                                                        "notify": false,
                                                        "external_id": "123456789",
                                                        "display_name": "Jane Doe",
                                                        "username": "janedoe",
                                                        "linked_at": "2026-05-18T10:05:00Z"
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-mcp-tools": [
                    "get_subscriber"
                ]
            }
        },
        "/v1/projects/{project}/members/{member}/identities": {
            "get": {
                "operationId": "v1.members.identities.index",
                "description": "```bash\ncurl https://api.subscriby.net/v1/projects/$PROJECT_ID/members/$MEMBER_ID/identities \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe member's connected accounts, preferred first. Never paginated. A member can connect one account per platform the project is on, from the portal's **Account & Recovery** screen or by talking to the project's bot; the member read embeds the same rows as `identities`. Connecting has no endpoint: it is a two-sided proof the member completes on the connector.\n\n- `id` is the link, which is what the disconnect endpoint takes; `external_id` is the platform's own id for the account.\n- `source` says how the link was proven: `handshake` (connected from the portal and confirmed by the bot, or a portal sign-in), `adopted` (taken over from another of the creator's projects), `portal`, `bot` (the bot met the account first) or `backfill` (migrated from before connectors).\n- `preferred` marks the account the project reaches first; a member's first account is, and the member can move it on the portal.\n- `notify` marks a further account the member switched the project's notices on for, from the portal. The preferred account always hears them, so it reads `false` there too; a grant notice stays on the connector of the grant and a support reply on the connector the member wrote from, whatever the switches say.",
                "summary": "List a member's connected accounts",
                "tags": [
                    "Members"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "member",
                        "in": "path",
                        "required": true,
                        "description": "The member, resolved within the project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Array of `MemberIdentityResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "$ref": "#/components/schemas/MemberIdentityResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "6a1f0c3e-2d4b-4e8a-9c7d-1b5e3f9a2c4d",
                                                    "connector": "telegram",
                                                    "source": "handshake",
                                                    "preferred": true,
                                                    "notify": false,
                                                    "external_id": "123456789",
                                                    "display_name": "Ada Lovelace",
                                                    "username": "ada",
                                                    "linked_at": "2026-09-12T10:05:00Z"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-mcp-tools": [
                    "list_member_identities"
                ]
            }
        },
        "/v1/projects/{project}/members/{member}/ban": {
            "post": {
                "operationId": "v1.members.ban",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/members/$MEMBER_ID/ban \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"reason\": \"Repeated spam in the research channel.\"}'\n```\n\nMoves a `lead`, `customer`, `trialing` or `churned` member to `banned`, removes their access on every connector and emits `member.banned` with the optional `reason`. Answers `200` with the member; a member already banned is answered unchanged and emits nothing.\n\nConnector-side eviction (kicks from the gated spaces, revoked invite links) runs asynchronously on the connector pipeline after the flip. The call returns as soon as Subscriby's state has been updated and the webhook event has been fired; the platform actions complete in the background.",
                "summary": "Ban a member",
                "tags": [
                    "Members"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "member",
                        "in": "path",
                        "required": true,
                        "description": "The member, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "reason": {
                                        "type": "string",
                                        "description": "Why the member is banned; carried on the `member.banned` event and shown in the dashboard, never sent to the member."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The member after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/MemberResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-user:update"
                ],
                "x-webhook-events": [
                    "member.banned"
                ],
                "x-mcp-tools": [
                    "ban_member"
                ]
            }
        },
        "/v1/projects/{project}/members/{member}/kick": {
            "post": {
                "operationId": "v1.members.kick",
                "description": "Moves the member to `churned`, removes them from every resource and emits `member.kicked` with the optional `reason`. Unlike a ban, a kicked member may come back by subscribing again. Answers `200` with the member; a `banned` member is answered unchanged, since a ban already says more. As with a ban, the connector-side eviction completes in the background after the call returns.",
                "summary": "Kick a member",
                "tags": [
                    "Members"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "member",
                        "in": "path",
                        "required": true,
                        "description": "The member, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "reason": {
                                        "type": "string",
                                        "description": "Why the member is removed; carried on the `member.kicked` event and shown in the dashboard, never sent to the member."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The member after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/MemberResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-user:update"
                ],
                "x-webhook-events": [
                    "member.kicked"
                ],
                "x-mcp-tools": [
                    "kick_member"
                ]
            }
        },
        "/v1/projects/{project}/members/{member}/unban": {
            "post": {
                "operationId": "v1.members.unban",
                "description": "Moves a `banned` member to `churned` and emits `member.unbanned`. Access is not restored: the member subscribes again from the portal or the bot. Answers `200` with the member; a member who is not banned is answered unchanged and emits nothing.",
                "summary": "Unban a member",
                "tags": [
                    "Members"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "member",
                        "in": "path",
                        "required": true,
                        "description": "The member, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The member after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/MemberResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-user:update"
                ],
                "x-webhook-events": [
                    "member.unbanned"
                ],
                "x-mcp-tools": [
                    "unban_member"
                ]
            }
        },
        "/v1/projects/{project}/members/{member}/identities/{link}": {
            "delete": {
                "operationId": "v1.members.identities.destroy",
                "description": "```bash\ncurl -X DELETE https://api.subscriby.net/v1/projects/$PROJECT_ID/members/$MEMBER_ID/identities/$LINK_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nDisconnects an account on the creator's behalf, the counterpart of the member's own Disconnect on the portal: it no longer signs the member in and the bot no longer knows them by it. Answers an empty `204` and emits `member.identity_unlinked`.",
                "summary": "Disconnect a member's account",
                "tags": [
                    "Members"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "member",
                        "in": "path",
                        "required": true,
                        "description": "The member, resolved within the project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "link",
                        "in": "path",
                        "required": true,
                        "description": "The member's link, resolved within the member.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: for a link that is not that member's.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the account is the member's last way to sign in (no verified email, linked Google account or other connected account remains).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-user:update"
                ],
                "x-webhook-events": [
                    "member.identity_unlinked"
                ],
                "x-mcp-tools": [
                    "unlink_member_identity"
                ]
            }
        },
        "/v1/me/notifications": {
            "get": {
                "operationId": "v1.me.notifications.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/me/notifications?unread=1&class=support\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nNewest first, paginated with `page` and `per_page` like every list. `unread=1` narrows to entries not yet read (`unread=0` to the ones already read); `class` narrows to one class; `q` to entries whose title or body contains the words.\n\n- `class` is the alert class the creator routes on **Settings → Notifications**: `sales`, `support`, `recovery`, `billing`, `security`, `passes` or `onboarding`; `class_label` is its name in the creator's language.\n- `title` and `body` are the alert's heading and one sentence of context, the same words the email used, in the creator's language at the time it was sent.\n- `route` and `params` name the dashboard screen the entry opens, as a named route and its parameters, for a client that maps routes to screens; `url` is the same place resolved, for a client that does not. All three are `null` when the alert points nowhere.\n- `read` is whether the creator opened it; `read_at` says when.\n\nEvery creator alert is written to the notification centre beside whatever else it sends (the email, the message on a connected account the creator routed it to on **Settings → Notifications**). The entry is shaped from the alert's email: its subject becomes the title, its first line the body, its call to action the route and URL. There is no webhook for a new entry; the alerts that matter to an integration already fire their own events (`recovery.*`, `connector.*`, `support.*`), and a Zap that wants the inbox itself polls the `notification_received` trigger.",
                "summary": "List the caller's notifications",
                "tags": [
                    "Notifications"
                ],
                "parameters": [
                    {
                        "name": "unread",
                        "in": "query",
                        "description": "`1` narrows to entries not yet read, `0` to the ones already read; omit it for both.",
                        "schema": {
                            "type": [
                                "boolean",
                                "null"
                            ]
                        }
                    },
                    {
                        "name": "class",
                        "in": "query",
                        "description": "Narrow to one alert class: `sales`, `support`, `recovery`, `billing`, `security`, `passes` or `onboarding`. An unknown class is refused.",
                        "schema": {
                            "anyOf": [
                                {
                                    "$ref": "#/components/schemas/AlertClass"
                                },
                                {
                                    "type": "null"
                                }
                            ]
                        }
                    },
                    {
                        "name": "q",
                        "in": "query",
                        "description": "Words the title or body must contain, up to 120 characters.",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "maxLength": 120
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 15.",
                        "schema": {
                            "type": "integer",
                            "default": 15,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page, newest first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/NotificationResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "0b1f6e2a-7c3d-4e5f-8a9b-0c1d2e3f4a5b",
                                                    "class": "support",
                                                    "class_label": "Support",
                                                    "title": "Support backlog in Signals",
                                                    "body": "Three members are waiting for an answer.",
                                                    "route": "projects.inbox",
                                                    "params": {
                                                        "projectId": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                                    },
                                                    "url": "https://app.subscriby.net/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/inbox",
                                                    "read": false,
                                                    "read_at": null,
                                                    "created_at": "2026-09-12T10:05:30Z"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `class` is not one of the seven classes.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-mcp-tools": [
                    "list_notifications"
                ]
            }
        },
        "/v1/me/notifications/read-all": {
            "post": {
                "operationId": "v1.me.notifications.read-all",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/me/notifications/read-all \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nAnswers `200` with how many entries were unread and are read now. A second call marks nothing and answers `0`.",
                "summary": "Mark every notification read",
                "tags": [
                    "Notifications"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with how many rows were marked.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "marked": {
                                                    "type": "integer",
                                                    "description": "How many entries were unread and are read now.",
                                                    "examples": [
                                                        3
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "marked"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "marked": 3
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:write"
                ],
                "x-mcp-tools": [
                    "mark_all_notifications_read"
                ]
            }
        },
        "/v1/me/notifications/{notification}/read": {
            "post": {
                "operationId": "v1.me.notifications.read",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/me/notifications/$NOTIFICATION_ID/read \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nAnswers `200` with the entry, `read` now `true`. Idempotent: an entry already read keeps its first `read_at`.",
                "summary": "Mark a notification read",
                "tags": [
                    "Notifications"
                ],
                "parameters": [
                    {
                        "name": "notification",
                        "in": "path",
                        "required": true,
                        "description": "The row, resolved by the route binder as the caller's.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with the row, read.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/NotificationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: for an id that is not one of the caller's entries.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:write"
                ],
                "x-mcp-tools": [
                    "mark_notification_read"
                ]
            }
        },
        "/v1/me/partner": {
            "get": {
                "operationId": "v1.me.partner.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/me/partner \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nWhere you stand, whole. `status` is `applied` while Subscriby reviews the application, `active` once approved, `rejected` with `reapply_available_at` when it was declined, or `suspended`. Until approval the computed parts are `null`: there is no `code`, no `links`, no `commission_percent`, no `balance`.\n\nOnce approved:\n\n- `code` is the seven-character partner code and `links.web` the address to hand out; `links.connectors` carries one deep link per connector whose bot signs creators up, each opening the sign-up conversation with the code attached.\n- `commission_percent` is the rate a creator who converts **from now on** is locked to, as a decimal string with two places. It is a ladder: `base_percent` plus `commitment_points` (the verified promotion commitments) plus `volume_points` (the volume tiers reached at `paying_referrals`), capped at `max_percent`; `next_tier_at` and `next_tier_points` say what the next tier takes and adds. A referral keeps the rate it was promised at conversion; a raise reaches every referral still inside its commission period, a drop only new conversions.\n- `referrals` tallies the creators brought in by state, and `balance` carries the ledger's sums as decimal strings with four places in `currency`: `pending` (inside the hold), `payable` (approved and not yet settled, clawbacks netted), `credited`, `paid` and `earned` (all of them together).\n- `commitments` lists every promotion commitment with its proof state; a commitment is made and its proof submitted on the dashboard or in the bot, where the rules are explained.",
                "summary": "Get your partnership",
                "tags": [
                    "Partner Program"
                ],
                "responses": {
                    "200": {
                        "description": "The partner object; 404 `RESOURCE_NOT_FOUND` until the caller applies.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PartnerResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "4b7e2d19-5c3a-4f80-9e6b-1d2c3b4a5f60",
                                                "status": "active",
                                                "code": "ADA7Q2X",
                                                "links": {
                                                    "web": "https://app.subscriby.net/r/ADA7Q2X",
                                                    "connectors": [
                                                        {
                                                            "connector": "telegram",
                                                            "name": "Telegram",
                                                            "url": "https://t.me/SubscribyBot?start=partner_ADA7Q2X"
                                                        }
                                                    ]
                                                },
                                                "commission_percent": "15.00",
                                                "base_percent": 5,
                                                "max_percent": 30,
                                                "commitment_points": 10,
                                                "volume_points": 0,
                                                "paying_referrals": 3,
                                                "next_tier_at": 10,
                                                "next_tier_points": 5,
                                                "commission_months": 12,
                                                "hold_days": 30,
                                                "minimum_cash_payout": "50",
                                                "friend_discount_percent": 20,
                                                "friend_discount_months": 3,
                                                "currency": "USD",
                                                "clicks": 412,
                                                "referrals": {
                                                    "total": 7,
                                                    "signed_up": 3,
                                                    "converted": 3,
                                                    "under_review": 0,
                                                    "expired": 1,
                                                    "rejected": 0
                                                },
                                                "balance": {
                                                    "pending": "11.7000",
                                                    "payable": "52.6500",
                                                    "credited": "0.0000",
                                                    "paid": "117.0000",
                                                    "earned": "181.3500"
                                                },
                                                "payout_method": "paypal",
                                                "payout_details_complete": true,
                                                "legal_name": "Ada Lovelace",
                                                "tax_country": "GB",
                                                "us_person": false,
                                                "terms_accepted_at": "2026-10-02T09:14:02+00:00",
                                                "terms_version": "2026-10-10",
                                                "commitments": [
                                                    {
                                                        "id": "9c1d2e3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f",
                                                        "kind": "long_form_video",
                                                        "status": "verified",
                                                        "audience_channel": "youtube",
                                                        "audience_url": "https://www.youtube.com/@ada",
                                                        "reach": "up_to_50k",
                                                        "points": 10,
                                                        "proof_url": "https://www.youtube.com/watch?v=example",
                                                        "promised_at": "2026-10-01T09:14:02+00:00",
                                                        "due_at": "2026-12-01T09:14:02+00:00",
                                                        "proof_submitted_at": "2026-10-20T16:41:11+00:00",
                                                        "verified_at": "2026-10-21T08:00:00+00:00",
                                                        "lapsed_at": null,
                                                        "created_at": "2026-10-01T09:14:02+00:00"
                                                    }
                                                ],
                                                "applied_at": "2026-10-01T09:14:02+00:00",
                                                "joined_at": "2026-10-02T09:14:02+00:00",
                                                "rejected_at": null,
                                                "rejection_reason": null,
                                                "reapply_available_at": null,
                                                "suspended_at": null,
                                                "created_at": "2026-10-01T09:14:02+00:00",
                                                "updated_at": "2026-10-21T08:00:00+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: until the caller applies.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-mcp-tools": [
                    "get_partner_program"
                ]
            }
        },
        "/v1/me/partner/referrals": {
            "get": {
                "operationId": "v1.me.partner.referrals.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/me/partner/referrals?status=converted&per_page=25\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nPages the creators you brought to Subscriby, newest first. `status` is `signed_up`, `converted`, `under_review`, `expired` or `rejected`. Each row names the referred creator by display name alone: they are a Subscriby customer, not yours, so their email and id never appear. An application still under review has no referrals and answers an empty page.",
                "summary": "List your referrals",
                "tags": [
                    "Partner Program"
                ],
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "description": "Keep only referrals in this state: `signed_up`, `converted`, `under_review`, `expired` or `rejected`.",
                        "schema": {
                            "$ref": "#/components/schemas/PartnerReferralStatus"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/PartnerReferralResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-mcp-tools": [
                    "list_partner_referrals"
                ]
            }
        },
        "/v1/me/partner/referrals/{referral}": {
            "get": {
                "operationId": "v1.me.partner.referrals.show",
                "description": "One referral: how the creator arrived (`source` is `link`, `code_at_signup` or `bot_deep_link`), whether their first paid invoice converted them and on which `plan`, the `commission_percent` locked onto them at conversion, and `commission_ends_at`, when you stop earning on them. Another partner's referral is `404 RESOURCE_NOT_FOUND`.",
                "summary": "Get a referral",
                "tags": [
                    "Partner Program"
                ],
                "parameters": [
                    {
                        "name": "referral",
                        "in": "path",
                        "required": true,
                        "description": "The referral, resolved within the caller's partnership by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The referral.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PartnerReferralResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "3c4d5e6f-7081-4a2b-9c3d-4e5f6a7b8c9d",
                                                "referred_name": "Grace Hopper",
                                                "source": "link",
                                                "status": "converted",
                                                "plan": "starter",
                                                "signed_up_at": "2026-10-08T11:00:00+00:00",
                                                "expires_at": "2027-04-06T11:00:00+00:00",
                                                "converted_at": "2026-10-09T14:20:00+00:00",
                                                "commission_percent": "15.00",
                                                "commission_ends_at": "2027-10-09T14:20:00+00:00",
                                                "created_at": "2026-10-08T11:00:00+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-mcp-tools": [
                    "get_partner_referral"
                ]
            }
        },
        "/v1/me/partner/rewards": {
            "get": {
                "operationId": "v1.me.partner.rewards.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/me/partner/rewards?status=approved\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nPages the commission ledger, newest first: one `commission` row per paid platform invoice of a referred creator, priced from the invoice's total before tax and after discount (`base_amount`) at the referral's locked rate (`amount`), plus the `clawback` rows that answer a reversal of money already settled, each with a negative `amount`. `status` is `pending` (inside the hold), `approved` (payable), `credited` (applied as Subscriby Credit), `paid` (covered by a cash payout) or `reversed`; `note` says why a row was reversed or re-priced. The ledger is read-only on every surface: rows are written by invoices, moved by the hold, settled by a credit or a payout and reversed by a refund or a dispute.",
                "summary": "List your commissions",
                "tags": [
                    "Partner Program"
                ],
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "description": "Keep only rows in this state: `pending`, `approved`, `credited`, `paid` or `reversed`.",
                        "schema": {
                            "$ref": "#/components/schemas/PartnerRewardStatus"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/PartnerRewardResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL.",
                                                    "examples": [
                                                        "https://api.subscriby.net/v1/me/partner/rewards?page=1"
                                                    ]
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL.",
                                                    "examples": [
                                                        "https://api.subscriby.net/v1/me/partner/rewards?page=1"
                                                    ]
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page.",
                                                    "examples": [
                                                        null
                                                    ]
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page.",
                                                    "examples": [
                                                        null
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs.",
                                                    "examples": [
                                                        "https://api.subscriby.net/v1/me/partner/rewards"
                                                    ]
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "examples": [
                                                        25
                                                    ],
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "8e9f0a1b-2c3d-4e5f-8a9b-0c1d2e3f4a5b",
                                                    "referral_id": "3c4d5e6f-7081-4a2b-9c3d-4e5f6a7b8c9d",
                                                    "kind": "commission",
                                                    "invoice_id": "in_1QExampleInvoice00",
                                                    "base_amount": "31.2000",
                                                    "amount": "4.6800",
                                                    "currency": "USD",
                                                    "status": "approved",
                                                    "hold_until": "2026-11-08T14:20:00+00:00",
                                                    "approved_at": "2026-11-08T15:00:00+00:00",
                                                    "credited_at": null,
                                                    "paid_at": null,
                                                    "reversed_at": null,
                                                    "payout_id": null,
                                                    "reverses_reward_id": null,
                                                    "note": null,
                                                    "created_at": "2026-10-09T14:20:00+00:00"
                                                }
                                            ],
                                            "links": {
                                                "first": "https://api.subscriby.net/v1/me/partner/rewards?page=1",
                                                "last": "https://api.subscriby.net/v1/me/partner/rewards?page=1",
                                                "prev": null,
                                                "next": null
                                            },
                                            "meta": {
                                                "current_page": 1,
                                                "from": 1,
                                                "last_page": 1,
                                                "path": "https://api.subscriby.net/v1/me/partner/rewards",
                                                "per_page": 25,
                                                "to": 1,
                                                "total": 1
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-mcp-tools": [
                    "list_partner_rewards"
                ]
            }
        },
        "/v1/me/partner/payouts": {
            "get": {
                "operationId": "v1.me.partner.payouts.index",
                "description": "Pages the cash Subscriby paid you, newest first: the `amount`, the rail it went by (`method` is `paypal`, `wise`, `remitly` or `crypto`), the transfer's `reference`, when it left and how many commissions it covered (`rewards_paid`). Commissions settled as Subscriby Credit are not payouts; they read as `credited` on the rewards list.",
                "summary": "List your payouts",
                "tags": [
                    "Partner Program"
                ],
                "parameters": [
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/PartnerPayoutResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL.",
                                                    "examples": [
                                                        "https://api.subscriby.net/v1/me/partner/payouts?page=1"
                                                    ]
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL.",
                                                    "examples": [
                                                        "https://api.subscriby.net/v1/me/partner/payouts?page=1"
                                                    ]
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page.",
                                                    "examples": [
                                                        null
                                                    ]
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page.",
                                                    "examples": [
                                                        null
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs.",
                                                    "examples": [
                                                        "https://api.subscriby.net/v1/me/partner/payouts"
                                                    ]
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "examples": [
                                                        25
                                                    ],
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "0b1c2d3e-4f50-4617-8a9b-0c1d2e3f4a5b",
                                                    "amount": "117.0000",
                                                    "currency": "USD",
                                                    "method": "paypal",
                                                    "reference": "PAYPAL-7F3D1C92",
                                                    "note": null,
                                                    "paid_at": "2026-11-01T06:30:00+00:00",
                                                    "rewards_paid": 10,
                                                    "created_at": "2026-11-01T06:30:00+00:00"
                                                }
                                            ],
                                            "links": {
                                                "first": "https://api.subscriby.net/v1/me/partner/payouts?page=1",
                                                "last": "https://api.subscriby.net/v1/me/partner/payouts?page=1",
                                                "prev": null,
                                                "next": null
                                            },
                                            "meta": {
                                                "current_page": 1,
                                                "from": 1,
                                                "last_page": 1,
                                                "path": "https://api.subscriby.net/v1/me/partner/payouts",
                                                "per_page": 25,
                                                "to": 1,
                                                "total": 1
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-mcp-tools": [
                    "list_partner_payouts"
                ]
            }
        },
        "/v1/me/partner/payout-details": {
            "put": {
                "operationId": "v1.me.partner.payout-details.update",
                "description": "```bash\ncurl -X PUT https://api.subscriby.net/v1/me/partner/payout-details \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"method\": \"paypal\",\n    \"details\": \"ada@example.com\",\n    \"legal_name\": \"Ada Lovelace\",\n    \"tax_country\": \"GB\",\n    \"us_person\": false,\n    \"accept_terms\": true\n  }'\n```\n\nWrites how you are paid: the rail, what it pays to, and the tax declaration every cash rail needs. `paypal` and `crypto` take their one `details` (the PayPal email, the USDT TRC20 wallet address); `wise` and `remitly` take the bank account (`bank_holder`, `bank_name`, `bank_country`, `bank_account_number`, and `bank_swift`, `bank_branch_code`, `bank_address` when the transfer needs them); `credit` takes nothing and is accepted while that rail is open. Only the destination the chosen rail uses is kept, encrypted; a rail you leave behind keeps nothing on file. The response is the partner object with `payout_method` and `payout_details_complete` updated and the destination absent.\n\n> **The terms come first.** A rail cannot be saved until you have accepted the Partner Program Terms: send `accept_terms: true` here, or call the terms endpoint before.",
                "summary": "Set your payout details",
                "tags": [
                    "Partner Program"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdatePartnerPayoutDetailsRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The partner object after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PartnerResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: until the caller applies.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when a field is invalid or missing for the rail, when the terms are not accepted, when the credit rail is closed, when the bank account is incomplete, or while the application is under review or was declined.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:write"
                ],
                "x-mcp-tools": [
                    "update_partner_payout_details"
                ]
            }
        },
        "/v1/me/partner/terms/accept": {
            "post": {
                "operationId": "v1.me.partner.terms.accept",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/me/partner/terms/accept \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nRecords that you accept the [Partner Program Terms](https://www.subscriby.net/legal/partners) as they stand today, with their version; accepting again after the terms change is the same call. Answers the partner object with `terms_accepted_at` and `terms_version` set. Emits no event.",
                "summary": "Accept the Partner Program Terms",
                "tags": [
                    "Partner Program"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The partner object after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PartnerResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: until the caller applies.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: while the application is under review or was declined.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:write"
                ],
                "x-mcp-tools": [
                    "accept_partner_terms"
                ]
            }
        },
        "/v1/projects/{project}/pass-windows": {
            "get": {
                "operationId": "v1.pass-windows.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/$PROJECT_ID/pass-windows?status=scheduled&sellable_only=true\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe project's windows across every pass plan, **soonest first**, 50 per page (`per_page` 1 to 100; `limit` is accepted as an alias). Filters are validated before they reach the query: an unknown status or a malformed date is a `422 VALIDATION_FAILED` naming the field, not an empty page.\n\n> **The list also opens to `project-subscription-plan:view-any`.** The list shipped under the plan ability before the `pass-window:*` family had any surface, and it is what the n8n node and the MCP tool docs named. A token holding only `project-subscription-plan:view-any` therefore still satisfies the `pass-window:view-any` gate. Mint new tokens with the precise ability; the alias exists so old ones keep working.",
                "summary": "List a project's pass windows",
                "tags": [
                    "Pass Windows"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "plan_id",
                        "in": "query",
                        "description": "One pass plan of the project only.",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "description": "One state only: `scheduled`, `open`, `closed` or `canceled`. Anything else is refused.",
                        "schema": {
                            "anyOf": [
                                {
                                    "$ref": "#/components/schemas/PassWindowStatus"
                                },
                                {
                                    "type": "null"
                                }
                            ]
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "description": "Only windows starting at or after this moment, ISO 8601.",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "format": "date-time"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "description": "Only windows starting at or before this moment, ISO 8601.",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "format": "date-time"
                        }
                    },
                    {
                        "name": "sellable_only",
                        "in": "query",
                        "description": "Keep only windows a buyer could still purchase.",
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 50.",
                        "schema": {
                            "type": "integer",
                            "default": 50,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page, soonest first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/PassWindowResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `status` is not one of the four states, `plan_id` is not a UUID, or `from` or `to` is not a date.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "pass-window:view-any"
                ],
                "x-mcp-tools": [
                    "list_pass_windows"
                ]
            }
        },
        "/v1/projects/{project}/pass-windows/{window}": {
            "get": {
                "operationId": "v1.pass-windows.show",
                "description": "One window, with `sellable` and `holders` resolved for it. A window is resolved **within the project**: a window id that belongs to another project, another team, or to nothing at all is a `404 RESOURCE_NOT_FOUND`, so an id's existence never leaks.\n\n| Field              | Type    | Notes                                                                                                                                          |\n| ------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |\n| `starts_at`        | string  | ISO 8601, **UTC**. Store this.                                                                                                                 |\n| `ends_at`          | string  | ISO 8601, UTC.                                                                                                                                 |\n| `timezone`         | string  | The IANA zone the plan's schedule was authored in. Render window times in this, never in UTC.                                                  |\n| `local_range`      | string  | The same window as a person reads it, already in `timezone`: what the dashboard, the portal and the bot all print.                             |\n| `duration_minutes` | integer | Derived from the two instants.                                                                                                                 |\n| `status`           | string  | `scheduled`, `open`, `closed` or `canceled`. Set by the scheduler as the window's start and end pass; `canceled` only by an explicit cancel.   |\n| `source`           | string  | `generated` from the plan's slots, or `manual` when placed by hand. Manual windows survive a schedule rebuild; generated ones are regenerated. |\n| `sellable`         | boolean | Whether a buyer could purchase this window right now: the plan's sales cutoff, resolved for the whole page in one query rather than per row.   |\n| `holders`          | integer | How many purchases currently hold the window.                                                                                                  |\n\n> **Why both UTC and a local range.** A pass schedule is authored in the creator's zone and rendered in it everywhere else in the product. Returning only UTC would leave every consumer converting, and getting it wrong across a daylight-saving boundary. `starts_at` is for storing and comparing; `local_range` is for showing.",
                "summary": "Get a pass window",
                "tags": [
                    "Pass Windows"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "window",
                        "in": "path",
                        "required": true,
                        "description": "The window, resolved within the project with its holder count and sale flag.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The window.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PassWindowResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                                "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "plan_name": "Match Day Pass",
                                                "starts_at": "2026-09-20T13:00:00+00:00",
                                                "ends_at": "2026-09-20T16:00:00+00:00",
                                                "timezone": "America/New_York",
                                                "local_range": "Sun 20 Sep 2026, 09:00 – 12:00 EDT",
                                                "duration_minutes": 180,
                                                "status": "scheduled",
                                                "source": "generated",
                                                "sellable": true,
                                                "holders": 38
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "pass-window:view"
                ],
                "x-mcp-tools": [
                    "get_pass_window"
                ]
            }
        },
        "/v1/projects/{project}/plans/{plan}/pass-windows": {
            "post": {
                "operationId": "v1.pass-windows.store",
                "description": "Places a window by hand on a `kind: pass` plan. This is how `schedule_mode: fixed` gets its dates, and how a repeating plan gets the one-off that does not fit its pattern.\n\n```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/plans/$PLAN_ID/pass-windows \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"starts_at\": \"2026-09-20 09:00\",\n    \"duration_minutes\": 180\n  }'\n```\n\nAnswers `201` with the new window: `status: scheduled`, `source: manual`, `holders: 0`. The request above and `\"starts_at\": \"2026-09-20T09:00:00-04:00\"` describe the same instant for a plan in `America/New_York`, and both come back as `\"2026-09-20T13:00:00+00:00\"`. Raises `pass.window_scheduled` with `source: manual`.\n\nA manual window is never touched by regeneration: editing `pass.slots` on the plan rebuilds the generated windows and leaves this one where you put it. Every pass series with a rule is asked to look at the new date afterwards, so a matching series absorbs it as described on the [Plans](https://docs.subscriby.net/api/v1/reference/plans) page.\n\nEach refusal below is a `422 VALIDATION_FAILED` naming the field, the same wording the dashboard's panel shows.",
                "summary": "Place a pass window by hand",
                "tags": [
                    "Pass Windows"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "plan",
                        "in": "path",
                        "required": true,
                        "description": "The plan, resolved within the project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StorePassWindowRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The window.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PassWindowResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "9c1f4e27-5a8b-4d63-b2e0-8f7a6c5d4e31",
                                                "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "plan_name": "Match Day Pass",
                                                "starts_at": "2026-09-20T13:00:00+00:00",
                                                "ends_at": "2026-09-20T16:00:00+00:00",
                                                "timezone": "America/New_York",
                                                "local_range": "Sun 20 Sep 2026, 09:00 – 12:00 EDT",
                                                "duration_minutes": 180,
                                                "status": "scheduled",
                                                "source": "manual",
                                                "sellable": true,
                                                "holders": 0
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when the plan is not a time-limited pass: a subscription or a series has no windows of its own. `VALIDATION_FAILED`: when the start is in the past, judged in the plan's own zone. `VALIDATION_FAILED`: when the length is under the plan's floor or over its ceiling (5 minutes and 30 days by default). `VALIDATION_FAILED`: when the plan already has a window starting at that instant. `VALIDATION_FAILED`: when the plan stops selling a fixed number of minutes before a window **ends** and the window is not longer than that cutoff, so it would never be on sale while it runs.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "pass-window:create"
                ],
                "x-webhook-events": [
                    "pass.window_scheduled"
                ],
                "x-mcp-tools": [
                    "create_pass_window"
                ]
            }
        },
        "/v1/projects/{project}/pass-windows/{window}/cancel": {
            "post": {
                "operationId": "v1.pass-windows.cancel",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/pass-windows/$WINDOW_ID/cancel \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nThe body is optional. `series_holders` is the choice the dashboard's cancellation dialog asks for season-ticket holders: `substitute` (the default) moves them to the plan's next window on sale, keeping their season at the same length; `drop` removes the cancelled date from their season, leaves the rest standing and reports what the date was worth per holder. A weekly season always has a next date on sale, so without `drop` a day with no event hands its season-ticket holders a free date the following week while the single-date holders rightly roll forward. Single-date holders are always moved where a window is on sale.\n\n```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/pass-windows/$WINDOW_ID/cancel \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"series_holders\": \"drop\"}'\n```\n\nBy the time the response arrives every holder has been resettled, and `meta` says how:\n\n| Tally          | What happened to those holders                                                                                                                                    |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `rebound`      | Moved to the plan's next window on sale, and told so. Their invite links are re-issued ahead of the new window.                                                   |\n| `refund_due`   | The schedule had nothing left to offer, so their pass was ended. Their message states what they paid and that the refund is the creator's decision.               |\n| `legs_dropped` | Season-ticket holders who lost this one date and keep the rest of their series. Their message states what they paid, what the date was worth, and the same.        |\n\n`meta.refunds` lists every holder the cancellation left owed a decision, one row each (a holder who paid nothing is settled and counted in the tallies but listed nowhere, since there is nothing to decide): the member's name, the `reason` (`stranded` or `leg_dropped`), `amount_paid` and `amount` (what the cancelled date was worth) with their `_formatted` twins in the holder's own currency, the `currency`, and `passes_remaining`. `meta.refund_totals` adds the rows up per currency. These are the figures the holders were told, so the creator reads the same number the member will ask about.\n\n> **Subscriby never moves the refunds.** `refund_due`, `legs_dropped` and `refunds` are statements, not actions. The money stays where it is until the creator refunds it at the gateway. An integration that wants to act on them can read `meta.refunds` here, or subscribe to `pass.holder_stranded` and `pass_series.leg_dropped`, which carry the amount per holder.\n\nCancelling is a `POST` verb and not a `DELETE` on purpose: it resettles every holder, moving them on or ending their pass, which is far too consequential to read as removing a row. It also cannot be undone: the window keeps its start permanently, so the same instant can never be re-created on that plan.\n\nRaises `pass.window_cancelled` carrying the tallies, plus one event per holder: `pass.holder_moved` or `pass.holder_stranded` for ordinary passes, `pass_series.leg_substituted` or `pass_series.leg_dropped` for season-ticket holders. A window that is already cancelled is answered `200` with every tally at zero, so a retry after a lost response changes nothing.",
                "summary": "Cancel a pass window",
                "tags": [
                    "Pass Windows"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "window",
                        "in": "path",
                        "required": true,
                        "description": "The window, resolved within the project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CancelPassWindowRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The window, cancelled, with the tallies, the choice and the refunds under `meta`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PassWindowResource"
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "How every holder was resettled; every tally zero and every list empty when the window was already cancelled.",
                                            "properties": {
                                                "rebound": {
                                                    "type": "integer",
                                                    "description": "Holders moved to the plan's next window on sale and told so.",
                                                    "examples": [
                                                        38
                                                    ]
                                                },
                                                "refund_due": {
                                                    "type": "integer",
                                                    "description": "Single-date holders whose pass was ended because the schedule had nothing left, told what they paid.",
                                                    "examples": [
                                                        3
                                                    ]
                                                },
                                                "legs_dropped": {
                                                    "type": "integer",
                                                    "description": "Season-ticket holders who lost this one date and keep the rest of their series, told what it was worth.",
                                                    "examples": [
                                                        4
                                                    ]
                                                },
                                                "subscribers_affected": {
                                                    "type": "integer",
                                                    "description": "The three tallies added up.",
                                                    "examples": [
                                                        45
                                                    ]
                                                },
                                                "series_holders": {
                                                    "type": "string",
                                                    "description": "The choice applied to season-ticket holders: `substitute` or `drop`.",
                                                    "enum": [
                                                        "substitute",
                                                        "drop"
                                                    ],
                                                    "examples": [
                                                        "drop"
                                                    ]
                                                },
                                                "refunds": {
                                                    "type": "array",
                                                    "description": "One row per holder owed a decision: `subscription_id`, `subscriber_id`, `member`, `reason`, `amount`, `amount_paid`, their `_formatted` twins, `currency`, `passes_remaining`.",
                                                    "items": {}
                                                },
                                                "refund_totals": {
                                                    "type": "array",
                                                    "description": "The refunds added up per currency.",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "currency": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The ISO code the row's holders paid in; null for purchases that recorded none.",
                                                                "examples": [
                                                                    "USD"
                                                                ]
                                                            },
                                                            "amount": {
                                                                "type": "string",
                                                                "description": "The rows' amounts added up, two decimals.",
                                                                "examples": [
                                                                    "84.60"
                                                                ]
                                                            },
                                                            "formatted": {
                                                                "type": "string",
                                                                "description": "The same total with its currency symbol, as the holders' figures were formatted.",
                                                                "examples": [
                                                                    "$84.60"
                                                                ]
                                                            }
                                                        },
                                                        "required": [
                                                            "currency",
                                                            "amount",
                                                            "formatted"
                                                        ]
                                                    }
                                                }
                                            },
                                            "required": [
                                                "rebound",
                                                "refund_due",
                                                "legs_dropped",
                                                "subscribers_affected",
                                                "series_holders",
                                                "refunds",
                                                "refund_totals"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                                "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "plan_name": "Match Day Pass",
                                                "starts_at": "2026-09-20T13:00:00+00:00",
                                                "ends_at": "2026-09-20T16:00:00+00:00",
                                                "timezone": "America/New_York",
                                                "local_range": "Sun 20 Sep 2026, 09:00 – 12:00 EDT",
                                                "duration_minutes": 180,
                                                "status": "canceled",
                                                "source": "generated",
                                                "sellable": false,
                                                "holders": 0
                                            },
                                            "meta": {
                                                "rebound": 38,
                                                "refund_due": 3,
                                                "legs_dropped": 4,
                                                "subscribers_affected": 45,
                                                "series_holders": "drop",
                                                "refunds": [
                                                    {
                                                        "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                        "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                        "member": "Jane Fox",
                                                        "reason": "leg_dropped",
                                                        "amount": "9.90",
                                                        "amount_formatted": "$9.90",
                                                        "amount_paid": "99.00",
                                                        "amount_paid_formatted": "$99.00",
                                                        "currency": "USD",
                                                        "passes_remaining": 3
                                                    }
                                                ],
                                                "refund_totals": [
                                                    {
                                                        "currency": "USD",
                                                        "amount": "84.60",
                                                        "formatted": "$84.60"
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "pass-window:delete"
                ],
                "x-webhook-events": [
                    "pass.window_cancelled",
                    "pass.holder_moved",
                    "pass.holder_stranded",
                    "pass_series.leg_substituted",
                    "pass_series.leg_dropped"
                ],
                "x-mcp-tools": [
                    "cancel_pass_window"
                ]
            }
        },
        "/v1/projects/{project}/pass-windows/{window}/remind": {
            "post": {
                "operationId": "v1.pass-windows.remind",
                "description": "Nudges everyone who bought the window but has not yet joined, re-attaching their invite links. It is the panel's **Send Reminder** button; the automatic reminders a day and an hour before a window opens still run regardless.\n\n```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/pass-windows/$WINDOW_ID/remind \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\n`reminded` is how many holders the **connector accepted** a message for, not how many were attempted: a holder who has blocked the bot is skipped without costing the rest their nudge. A window that has ended or been cancelled reminds nobody and answers `0` rather than refusing. No event fires: the reminder is a message on the connector, not a state change.\n\nThis messages real people. Do not repeat it within the same window, and to nudge one holder rather than a whole window use the [subscription remind endpoint](https://docs.subscriby.net/api/v1/reference/subscriptions/remind-a-pass-holder).",
                "summary": "Remind a window's holders",
                "tags": [
                    "Pass Windows"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "window",
                        "in": "path",
                        "required": true,
                        "description": "The window, resolved within the project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "`window_id` and how many holders were `reminded`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "window_id": {
                                                    "type": "string",
                                                    "description": "The window that was reminded.",
                                                    "examples": [
                                                        "3d5a8c72-b016-4e94-8fa7-61c209d4e738"
                                                    ]
                                                },
                                                "reminded": {
                                                    "type": "integer",
                                                    "description": "How many holders the connector accepted a reminder for.",
                                                    "examples": [
                                                        12
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "window_id",
                                                "reminded"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "window_id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                                "reminded": 12
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "pass-window:update"
                ],
                "x-mcp-tools": [
                    "remind_pass_window_queue"
                ]
            }
        },
        "/v1/projects/{project}/payment-methods": {
            "get": {
                "operationId": "v1.payment-methods.index",
                "description": "```bash\ncurl https://api.subscriby.net/v1/projects/$PROJECT_ID/payment-methods \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nEvery payment method attached to the project, newest first.",
                "summary": "List a project's payment methods",
                "tags": [
                    "Payment Methods"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page, newest first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/PaymentMethodResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-payment-method:view-any"
                ],
                "x-mcp-tools": [
                    "list_payment_methods"
                ]
            }
        },
        "/v1/projects/{project}/payment-methods/{method}": {
            "get": {
                "operationId": "v1.payment-methods.show",
                "description": "The method without its credentials. A method is resolved within the project: a method id that does not belong to the project, or a project outside the caller's tenant, is `404 RESOURCE_NOT_FOUND`, so foreign rows never leak.\n\n- `provider` is the stored provider key: a gateway slug (`stripe`, `paypal`, `razorpay`, `paystack`, `ceypay`, `skrill`, `coinpayments`, `accesscode`) or a `connector:provider` key for a currency a connector brings (`telegram:stars` for Telegram Stars). A project carries one method per provider key and mode, so two connectors can each bring their own currency to the same project. Rows created before provider keys existed carried `platformcurrency`; the connector's data migration rewrites them, and until it has run that word still reads as the native method of the project's connector.\n- `connector` is the connector behind a native payment method (`telegram` for a `telegram:stars` row), `null` for every gateway and for access codes. A connector declares its native providers through its manifest's `native_payments` capability, and the dashboard offers one option per provider of every connector that is connected on the project.\n- `mode` is `test` or `live`. Drives which set of provider credentials is used.\n- `linked` is true once the provider handshake (OAuth callback, API-key verify, etc.) has completed successfully.\n- `active` is the creator's toggle. A linked-but-inactive method cannot be used to charge subscribers.\n\n> **Credentials never leave.** Provider credentials (API keys, webhook secrets, connected account ids, Stripe Connect onboarding state) live in the encrypted configuration and are **never** serialised through REST or MCP, even for tokens with `view` ability. The dashboard is the only surface that reveals them, and only to the creator.",
                "summary": "Get a payment method",
                "tags": [
                    "Payment Methods"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "method",
                        "in": "path",
                        "required": true,
                        "description": "The method, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The method without its credentials.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PaymentMethodResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "a15d70c8-3e46-4b92-b70f-58c9d2140e63",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "provider": "stripe",
                                                "connector": null,
                                                "mode": "live",
                                                "linked": true,
                                                "active": true,
                                                "created_at": "2026-05-18T10:05:00Z",
                                                "updated_at": "2026-05-18T10:05:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-payment-method:view"
                ],
                "x-mcp-tools": [
                    "get_payment_method"
                ]
            },
            "delete": {
                "operationId": "v1.payment-methods.destroy",
                "description": "```bash\ncurl -X DELETE https://api.subscriby.net/v1/projects/$PROJECT_ID/payment-methods/$METHOD_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nReturns `204 No Content`. The row is soft-deleted: subscriptions sold through it keep their gateway for refunds and history, and configuring the same provider and mode again later revives the row instead of creating a duplicate. Buyers lose that way to pay at once. Emits `project.payment_method.deleted` with a credential-free snapshot; an already-deleted id is a `404`.",
                "summary": "Delete a payment method",
                "tags": [
                    "Payment Methods"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "method",
                        "in": "path",
                        "required": true,
                        "description": "The method, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-payment-method:delete"
                ],
                "x-webhook-events": [
                    "project.payment_method.deleted"
                ],
                "x-mcp-tools": [
                    "delete_payment_method"
                ]
            }
        },
        "/v1/projects/{project}/payment-methods/{method}/activate": {
            "post": {
                "operationId": "v1.payment-methods.activate",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/payment-methods/$METHOD_ID/activate \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nOffers the method at checkout again and re-queues the plan sync for that gateway. Answers `200` with the method. Idempotent: switching a method to the state it is already in writes nothing and emits nothing; when the switch flips, `project.payment_method.updated` fires once with `changes.active`.\n\n> **Stripe needs its Connect handshake first.** A Stripe method whose Connect onboarding never finished is refused: the row exists only so the creator can resume onboarding, and switching it on would offer buyers a gateway that fails at checkout. Finish onboarding from the dashboard, the only place the Connect handshake can complete.",
                "summary": "Activate a payment method",
                "tags": [
                    "Payment Methods"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "method",
                        "in": "path",
                        "required": true,
                        "description": "The method, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The method, switched on.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PaymentMethodResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: for a Stripe method awaiting Connect onboarding.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-payment-method:update"
                ],
                "x-webhook-events": [
                    "project.payment_method.updated"
                ],
                "x-mcp-tools": [
                    "activate_payment_method"
                ]
            }
        },
        "/v1/projects/{project}/payment-methods/{method}/deactivate": {
            "post": {
                "operationId": "v1.payment-methods.deactivate",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/payment-methods/$METHOD_ID/deactivate \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nThe creator's switch. A deactivated method is no longer offered at checkout; the subscriptions already sold through it keep renewing with their gateway. Re-queues the plan sync like activating does. Answers `200` with the method; idempotent, and `project.payment_method.updated` fires once with `changes.active` when the switch flips.",
                "summary": "Deactivate a payment method",
                "tags": [
                    "Payment Methods"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "method",
                        "in": "path",
                        "required": true,
                        "description": "The method, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The method, switched off.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PaymentMethodResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-payment-method:update"
                ],
                "x-webhook-events": [
                    "project.payment_method.updated"
                ],
                "x-mcp-tools": [
                    "deactivate_payment_method"
                ]
            }
        },
        "/v1/projects/{project}/payment-methods/{method}/sync": {
            "post": {
                "operationId": "v1.payment-methods.sync",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/payment-methods/$METHOD_ID/sync \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nQueues a push of the project owner's plans into the gateway's catalogue (Stripe products and prices, PayPal, Razorpay or CoinPayments plans) and answers `202 Accepted`. The work runs in the background; each plan reports through `plan.sync_completed` as it lands. Queuing twice pushes the same catalogue twice, which is harmless.",
                "summary": "Sync a payment method's plans",
                "tags": [
                    "Payment Methods"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "method",
                        "in": "path",
                        "required": true,
                        "description": "The method, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "202": {
                        "description": "The method id and `sync_queued`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "payment_method_id": {
                                                    "type": "string",
                                                    "description": "The method whose catalogue is being pushed.",
                                                    "examples": [
                                                        "a15d70c8-3e46-4b92-b70f-58c9d2140e63"
                                                    ]
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "Always `sync_queued`: the push runs in the background.",
                                                    "const": "sync_queued",
                                                    "examples": [
                                                        "sync_queued"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "payment_method_id",
                                                "status"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "payment_method_id": "a15d70c8-3e46-4b92-b70f-58c9d2140e63",
                                                "status": "sync_queued"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: for a gateway that keeps no catalogue (a connector's native currency, access codes, the redirect gateways).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-payment-method:update"
                ],
                "x-mcp-tools": [
                    "sync_payment_method_plans"
                ]
            }
        },
        "/v1/ping": {
            "get": {
                "operationId": "v1.ping",
                "description": "```bash\ncurl https://api.subscriby.net/v1/ping\n```\n\nAnswers `200` with `data.status` of `ok`, the API version and the current server time in ISO 8601. No `Authorization` header is read and no rate limit applies, so a monitor may call it on a schedule.",
                "summary": "Check the API is up",
                "tags": [
                    "Ping"
                ],
                "responses": {
                    "200": {
                        "description": "The status, the API version and the current time.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "status": {
                                                    "type": "string",
                                                    "description": "Always `ok`: the application answered.",
                                                    "const": "ok",
                                                    "examples": [
                                                        "ok"
                                                    ]
                                                },
                                                "version": {
                                                    "type": "string",
                                                    "description": "The API version the host serves, `v1`.",
                                                    "const": "v1",
                                                    "examples": [
                                                        "v1"
                                                    ]
                                                },
                                                "timestamp": {
                                                    "type": "string",
                                                    "description": "The server's current time, ISO 8601 with offset.",
                                                    "examples": [
                                                        "2026-09-23T14:05:00+00:00"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "status",
                                                "version",
                                                "timestamp"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "status": "ok",
                                                "version": "v1",
                                                "timestamp": "2026-09-23T14:05:00+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/v1/projects/{project}/plans": {
            "get": {
                "operationId": "v1.plans.index",
                "description": "Pages the project's plans, every kind together, newest first. Read `kind` on each row to know which of `billing`, `pass` or `pass_series` it carries; `resources` is loaded on every row. `pass.upcoming_windows` is not served here: the pass windows endpoints list a plan's dates.",
                "summary": "List a project's plans",
                "tags": [
                    "Plans"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page, newest first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/PlanResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view-any"
                ],
                "x-mcp-tools": [
                    "list_plans"
                ]
            },
            "post": {
                "operationId": "v1.plans.store",
                "description": "`POST` takes the **same shape it returns**: `kind` plus the one matching block. Sending a block that does not match the kind is refused with `VALIDATION_FAILED` naming the offending key; silently ignoring it would let a caller believe they had set a billing cycle on a pass. Answers `201` with the plan in the same discriminated shape the read endpoint shows for each kind. A plan created on sale (`active: true`, the default) is queued for the push to the payment methods that keep a product catalogue (Stripe, PayPal, CoinPayments, Razorpay), so it is sellable through them within a minute; a draft is pushed when it is published.\n\n### Create a subscription\n\n```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/plans \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"kind\": \"subscription\",\n    \"name\": \"Premium Monthly\",\n    \"currency_id\": \"8f27a0d4-63be-4915-8c07-1a5d9e34b628\",\n    \"price\": 29.00,\n    \"resources\": [\"b73c5f21-9d80-4a6e-8215-4f70ce13a9d6\"],\n    \"billing\": { \"billing_cycle\": \"month\", \"billing_cycle_count\": 1, \"trial_days\": 7 }\n  }'\n```\n\n### Create a pass\n\n```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/plans \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"kind\": \"pass\",\n    \"name\": \"Sunday Slate Pass\",\n    \"currency_id\": \"8f27a0d4-63be-4915-8c07-1a5d9e34b628\",\n    \"price\": 15.00,\n    \"resources\": [\"b73c5f21-9d80-4a6e-8215-4f70ce13a9d6\"],\n    \"pass\": {\n      \"timezone\": \"America/New_York\",\n      \"schedule_mode\": \"repeating\",\n      \"recurrence\": \"weekly\",\n      \"sales_cutoff_minutes\": 60,\n      \"sales_cutoff_anchor\": \"before_start\",\n      \"slots\": [\n        { \"weekday\": 4, \"start_time\": \"19:00\", \"duration_minutes\": 180 },\n        { \"weekday\": 0, \"start_time\": \"09:00\", \"duration_minutes\": 840 }\n      ]\n    }\n  }'\n```\n\nSending `pass.slots` **replaces the whole schedule** and rebuilds future windows. Windows a customer has already bought keep their original times and are never moved or deleted; only unsold future windows are regenerated. `pass.windows` is different: it *adds* explicitly dated windows for `schedule_mode: fixed` and never replaces anything.\n\n### Create a pass series\n\nA series needs window ids, and those come from windows that already exist. Read them from `pass.upcoming_windows` on the source plan, from the pass windows endpoints, or from the [`list_pass_windows`](https://docs.subscriby.net/mcp/v1/tools/plan/list-pass-windows) MCP tool.\n\n```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/plans \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"kind\": \"pass_series\",\n    \"name\": \"Autumn Season Ticket\",\n    \"currency_id\": \"8f27a0d4-63be-4915-8c07-1a5d9e34b628\",\n    \"price\": 99.00,\n    \"pass_series\": {\n      \"prevent_overlaps\": true,\n      \"seat_cap\": 50,\n      \"presale_hours\": 48,\n      \"window_ids\": [\"3d5a8c72-b016-4e94-8fa7-61c209d4e738\", \"9c1f4e27-5a8b-4d63-b2e0-8f7a6c5d4e31\"],\n      \"rules\": [\n        { \"source_plan_id\": \"0b8e6a2f-4c1d-4e3a-9f52-7d6c1b2a3e45\", \"kind\": \"date_range\", \"from_at\": \"2026-09-01T00:00:00Z\", \"to_at\": \"2026-12-01T00:00:00Z\" }\n      ]\n    }\n  }'\n```\n\n> **`resources` is optional on a series only.** Every other kind must link at least one resource, or a purchase buys nothing. A series is the exception: each of its windows grants **that window's own plan's** resources, so a series with none still delivers exactly what was sold. Anything you do link here is a **lounge**, open for the whole span.\n\n> **Never put a slate window's resource in a series `resources`.** A lounge is granted **at purchase with no window** and kept until the season ends. Send a resource that one of your slate windows already opens and every holder is handed it permanently the moment they pay: the dates it was scheduled for stop gating anything, and a season ticket becomes a permanent key to that channel. The API accepts it, because a genuinely permanent room is a legitimate thing to sell. It is simply almost never what was meant. Keep `resources` for a holders-only room nothing on the slate opens; the slate's own channels are already granted by their own pass plans on their own dates. The dashboard warns when the two overlap. Over the API, checking is yours to do.\n\nRules keep working after the save: a matching window scheduled later is absorbed into the slate **and granted to everyone already holding the series**, at no charge. That emits [`pass_series.leg_added`](https://docs.subscriby.net/webhooks/v1/events/pass-series/pass-series-leg-added). Handpicked `window_ids` never grow on their own. The two compose; most real seasons use both.\n\n### Validation\n\nThe field-by-field rules are on each request field below. The rules that cross fields:\n\n- `name` must be unique within the project, compared without regard to case or surrounding spaces; a duplicate is refused on `name`.\n- `price` must be at least the **$1.00 USD equivalent** in `currency_id`, converted at the current rate. Payment providers reject dust amounts, so anything below that is unbuyable and is refused; the error names the minimum in both the plan's currency and USD.\n- `price` of exactly `0` publishes a **free plan**. Plans priced at zero can only be sold by a **Starter** or **Growth** account, never on Free: the platform fee is a share of what you charge, so a zero-priced plan earns nothing to share. On Free the call is refused on `price`. The rule enforced is that a plan may not be **simultaneously active and priced at `0`** on a creator whose plan cannot sell one, so an update that leaves a zero-priced plan off sale is allowed.\n- `currency_id` must be supported by at least one active payment method on the project.\n- At most one of `eligibility.newcomers_only`, `eligibility.customers_only` and `eligibility.churned_only` may be `true`.\n- `resources` is required with at least one id, **except on `kind: pass_series`**, where it is optional and means a lounge.\n- `billing.billing_cycle_count` must be `1` when `billing.billing_cycle` is `lifetime`; `billing.recurring` is refused as `true` when the currency is a crypto or platform currency.\n- `pass.sales_cutoff_anchor: before_end` requires `pass.sales_cutoff_minutes` of at least `5` and under the shortest slot's `duration_minutes`, and is refused outright when that shortest slot is `5` minutes or less. `before_first_end` and `before_last_start` are **series-only** anchors and are rejected on a pass plan, where a lone window is both the first and the last.\n- `pass_series.window_ids` needs **at least two** windows unless a rule will supply them; every id must belong to a pass plan on this project; with `prevent_overlaps` on, two windows that run at the same time are refused. `pass_series.rules[].take` is **required when `kind` is `next_n`**, because a count rule with no count is incomplete rather than \"all of them\". `pass_series.successor_plan_id` must be **another** `kind: pass_series` plan on the same project.",
                "summary": "Create a plan",
                "tags": [
                    "Plans"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StorePlanRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The new plan.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PlanResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: when `kind` is `pass` or `pass_series` and the project owner's account lacks Time-Limited Passes, bundled with Growth or available as the Passes add-on.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when a block does not match `kind`, `name` is taken, `price` is below the minimum or is `0` on a Free account, `currency_id` has no active payment method, two eligibility flags are set, or a per-kind rule above is broken; `error.fields` names the key.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:create"
                ],
                "x-webhook-events": [
                    "plan.created"
                ],
                "x-mcp-tools": [
                    "create_plan"
                ]
            }
        },
        "/v1/projects/{project}/plans/{plan}": {
            "get": {
                "operationId": "v1.plans.show",
                "description": "One plan in the same discriminated shape as the list. `kind` names the one block the plan carries, `billing`, `pass` or `pass_series`; the other two are absent. A plan of another project is `404 RESOURCE_NOT_FOUND`, because `{plan}` is resolved within `{project}`.\n\n### Common fields\n\nPresent on every kind.\n\n| Field         | Type   | Notes                                                                                                                                                                       |\n| ------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `kind`        | string | `subscription`, `pass` or `pass_series`. Names the one block below it.                                                                                                      |\n| `price`       | string | What **one purchase** costs. On a pass that buys one window; on a series it buys the whole slate, once.                                                                    |\n| `currency`    | object | `{ id, iso, symbol }`.                                                                                                                                                      |\n| `cadence`     | string | The human-readable duration string: `\"Per Month\"`, `\"Per 3 Hours\"`, `\"For all 10 passes\"`.                                                                                |\n| `eligibility` | object | Audience restrictions. The first three are mutually exclusive.                                                                                                              |\n| `resources`   | array  | Present when the relation is loaded: each resource's `id`, `name`, `kind` (`manual` or `connector:kind`) and `connector`. On a series these are the **lounge**, not the thing being sold. |\n\n> **Why `cadence` exists.** Both the portal and the bot already compute exactly this string, and every integrator without it reinvents it, wrongly for a dated plan, printing \"1 Month\" beside a three-hour window. Use it rather than deriving a duration from the cycle fields.\n\n### kind: subscription\n\n| Field                         | Type    | Notes                                                 |\n| ----------------------------- | ------- | ----------------------------------------------------- |\n| `billing.billing_cycle`       | string  | `day`, `week`, `month`, `year`, `lifetime`.           |\n| `billing.billing_cycle_count` | integer | 1–99. Must be `1` when `billing_cycle` is `lifetime`. |\n| `billing.recurring`           | boolean | Rejected as `true` for crypto or platform currencies. |\n| `billing.disabled_renewal`    | boolean | Charges once, then lapses rather than renewing.       |\n| `billing.trial_days`          | integer | 0–365.                                                |\n| `billing.trial_cardless`      | boolean | Whether the trial starts without a payment method.    |\n| `billing.trial_type`          | string  | `project` or `plan`: whose trial rule applies.        |\n\n### kind: pass\n\nA plan that owns its own dated windows and sells one per purchase.\n\n| Field                           | Type              | Notes                                                                                                                                                                       |\n| ------------------------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `pass.timezone`                 | string            | IANA zone the schedule was authored in. Render window times in this, never UTC.                                                                                             |\n| `pass.schedule_mode`            | string            | `repeating` or `fixed`.                                                                                                                                                     |\n| `pass.recurrence`               | string \\| null    | `daily`, `weekly` or `monthly`. Null in `fixed` mode.                                                                                                                       |\n| `pass.recurrence_ends_at`       | timestamp \\| null | When window generation stops. **Renamed**, see the note below.                                                                                                              |\n| `pass.sales_cutoff_minutes`     | integer \\| null   | Stops sales this many minutes before the moment `sales_cutoff_anchor` names.                                                                                                |\n| `pass.sales_cutoff_anchor`      | string            | `before_start` or `before_end`. Never null: a plan that never set it reads as `before_start`. `before_first_end` and `before_last_start` are series-only and refused here. |\n| `pass.slots[].start_time`       | string `HH:MM`    | Local wall-clock time in `timezone`.                                                                                                                                        |\n| `pass.slots[].duration_minutes` | integer           | Each slot carries its own length, so one plan can mix a 3-hour and a 14-hour window.                                                                                        |\n| `pass.upcoming_windows[]`       | array             | Present only when the relation is loaded. Timestamps are **UTC**. The pass windows endpoints list and manage a plan's dates.                                              |\n\n> **`series_ends_at` was renamed to `recurrence_ends_at`.** Same field, same meaning: how long this plan keeps generating windows from its recurrence. It never had anything to do with a Pass Series, but now that a series is a real plan kind, a field called `series_ends_at` sitting on a pass read as \"when this plan's series ends\", which is a different thing and one that does not exist here. Update any reader to the new key; there is no alias.\n\n### kind: pass_series\n\nA season ticket. It **owns no windows**: it points at windows that already exist on your pass plans, which is the whole distinction from `kind: pass`.\n\n| Field                                 | Type              | Notes                                                                                                                                                                                                                                                                                                |\n| ------------------------------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `pass_series.timezone`                | string            | Borrowed from the source plans; a series has no zone of its own. A series whose sources disagree is refused at authoring time.                                                                                                                                                                      |\n| `pass_series.prevent_overlaps`        | boolean           | Refuses to absorb a window clashing with one already on the slate.                                                                                                                                                                                                                                   |\n| `pass_series.sales_cutoff_minutes`    | integer           | Measured against the **whole season**, not one window.                                                                                                                                                                                                                                               |\n| `pass_series.sales_cutoff_anchor`     | string            | Four anchors, earliest deadline first. `before_start` closes before the **first** window opens. `before_first_end` closes during that opening window. `before_last_start` closes as the **last** window opens, so a buyer always gets one whole window. `before_end` closes as the last window ends. |\n| `pass_series.seat_cap`                | integer \\| null   | Concurrent holder limit. `null` is unlimited.                                                                                                                                                                                                                                                        |\n| `pass_series.seats_taken`             | integer           | Holders currently counted against the cap.                                                                                                                                                                                                                                                           |\n| `pass_series.seats_remaining`         | integer \\| null   | `null` when uncapped.                                                                                                                                                                                                                                                                                |\n| `pass_series.starts_at`               | timestamp \\| null | First window's start, **UTC**.                                                                                                                                                                                                                                                                       |\n| `pass_series.ends_at`                 | timestamp \\| null | Last window's end, UTC.                                                                                                                                                                                                                                                                              |\n| `pass_series.window_count`            | integer           | Slate length. Capped at **120**.                                                                                                                                                                                                                                                                     |\n| `pass_series.successor_plan_id`       | string \\| null    | The next season, offered to holders first when this one finishes.                                                                                                                                                                                                                                    |\n| `pass_series.presale_hours`           | integer \\| null   | How long that offer is held for holders only. 1–8760.                                                                                                                                                                                                                                                |\n| `pass_series.windows[]`               | array             | The slate. Each entry names the **plan the window belongs to**; a series can mix several.                                                                                                                                                                                                            |\n| `pass_series.windows[].added_by_rule` | boolean           | `true` when a rule absorbed it rather than the creator picking it by hand.                                                                                                                                                                                                                           |\n| `pass_series.rules[]`                 | array             | Automatic inclusion rules. `kind` is `date_range` or `next_n`; `take` is required on `next_n`.                                                                                                                                                                                                       |\n| `pass_series.blackout_window_ids`     | array             | Windows a rule matches but the creator has permanently excluded.                                                                                                                                                                                                                                     |",
                "summary": "Get a plan",
                "tags": [
                    "Plans"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "plan",
                        "in": "path",
                        "required": true,
                        "description": "The plan, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The plan.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PlanResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "subscription": {
                                        "summary": "Subscription",
                                        "value": {
                                            "data": {
                                                "id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "kind": "subscription",
                                                "name": "Premium Monthly",
                                                "description": "Unlimited access to the research channel.",
                                                "price": "29.00",
                                                "currency": {
                                                    "id": "8f27a0d4-63be-4915-8c07-1a5d9e34b628",
                                                    "iso": "USD",
                                                    "symbol": "$"
                                                },
                                                "active": true,
                                                "sales_cap": 10,
                                                "sales_cap_sold": 3,
                                                "position": 0,
                                                "paused": null,
                                                "cadence": "Per Month",
                                                "eligibility": {
                                                    "newcomers_only": false,
                                                    "customers_only": false,
                                                    "churned_only": false,
                                                    "single_use": false,
                                                    "access_codes_only": false
                                                },
                                                "resources": [
                                                    {
                                                        "id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                        "name": "Research channel",
                                                        "kind": "telegram:supergroup",
                                                        "connector": "telegram"
                                                    }
                                                ],
                                                "billing": {
                                                    "billing_cycle": "month",
                                                    "billing_cycle_count": 1,
                                                    "recurring": true,
                                                    "disabled_renewal": false,
                                                    "trial_days": 7,
                                                    "trial_cardless": false,
                                                    "trial_type": "plan"
                                                },
                                                "created_at": "2026-05-18T10:05:00Z",
                                                "updated_at": "2026-05-18T10:05:00Z"
                                            }
                                        }
                                    },
                                    "pass": {
                                        "summary": "Pass",
                                        "value": {
                                            "data": {
                                                "id": "0b8e6a2f-4c1d-4e3a-9f52-7d6c1b2a3e45",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "kind": "pass",
                                                "name": "Sunday Slate Pass",
                                                "description": "One Sunday in the research channel.",
                                                "price": "15.00",
                                                "currency": {
                                                    "id": "8f27a0d4-63be-4915-8c07-1a5d9e34b628",
                                                    "iso": "USD",
                                                    "symbol": "$"
                                                },
                                                "active": true,
                                                "sales_cap": null,
                                                "sales_cap_sold": 0,
                                                "position": 1,
                                                "paused": null,
                                                "cadence": "Per 3 Hours",
                                                "eligibility": {
                                                    "newcomers_only": false,
                                                    "customers_only": false,
                                                    "churned_only": false,
                                                    "single_use": false,
                                                    "access_codes_only": false
                                                },
                                                "resources": [
                                                    {
                                                        "id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                        "name": "Research channel",
                                                        "kind": "telegram:supergroup",
                                                        "connector": "telegram"
                                                    }
                                                ],
                                                "pass": {
                                                    "timezone": "America/New_York",
                                                    "schedule_mode": "repeating",
                                                    "recurrence": "weekly",
                                                    "recurrence_ends_at": null,
                                                    "sales_cutoff_minutes": 60,
                                                    "sales_cutoff_anchor": "before_start",
                                                    "slots": [
                                                        {
                                                            "weekday": 0,
                                                            "day_of_month": null,
                                                            "start_time": "09:00",
                                                            "duration_minutes": 840
                                                        }
                                                    ],
                                                    "upcoming_windows": [
                                                        {
                                                            "id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                                            "starts_at": "2026-09-20T13:00:00Z",
                                                            "ends_at": "2026-09-21T03:00:00Z",
                                                            "status": "scheduled"
                                                        }
                                                    ]
                                                },
                                                "created_at": "2026-05-18T10:05:00Z",
                                                "updated_at": "2026-05-18T10:05:00Z"
                                            }
                                        }
                                    },
                                    "pass-series": {
                                        "summary": "Pass series",
                                        "value": {
                                            "data": {
                                                "id": "e2c7a9d1-5f3b-4c8e-9a6d-1b4f7e2c8a53",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "kind": "pass_series",
                                                "name": "Autumn Season Ticket",
                                                "description": "Every match day of the autumn, in one purchase.",
                                                "price": "99.00",
                                                "currency": {
                                                    "id": "8f27a0d4-63be-4915-8c07-1a5d9e34b628",
                                                    "iso": "USD",
                                                    "symbol": "$"
                                                },
                                                "active": true,
                                                "sales_cap": null,
                                                "sales_cap_sold": 0,
                                                "position": 2,
                                                "paused": null,
                                                "cadence": "For all 10 passes",
                                                "eligibility": {
                                                    "newcomers_only": false,
                                                    "customers_only": false,
                                                    "churned_only": false,
                                                    "single_use": false,
                                                    "access_codes_only": false
                                                },
                                                "resources": [],
                                                "pass_series": {
                                                    "timezone": "America/New_York",
                                                    "prevent_overlaps": true,
                                                    "sales_cutoff_minutes": 0,
                                                    "sales_cutoff_anchor": "before_start",
                                                    "seat_cap": 50,
                                                    "seats_taken": 37,
                                                    "seats_remaining": 13,
                                                    "starts_at": "2026-09-20T13:00:00Z",
                                                    "ends_at": "2026-11-29T22:00:00Z",
                                                    "window_count": 10,
                                                    "successor_plan_id": null,
                                                    "presale_hours": 48,
                                                    "windows": [
                                                        {
                                                            "id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                                            "plan_id": "0b8e6a2f-4c1d-4e3a-9f52-7d6c1b2a3e45",
                                                            "plan_name": "Match Day Pass",
                                                            "starts_at": "2026-09-20T13:00:00Z",
                                                            "ends_at": "2026-09-20T16:00:00Z",
                                                            "status": "scheduled",
                                                            "added_by_rule": false
                                                        }
                                                    ],
                                                    "rules": [
                                                        {
                                                            "source_plan_id": "0b8e6a2f-4c1d-4e3a-9f52-7d6c1b2a3e45",
                                                            "kind": "date_range",
                                                            "from_at": "2026-09-01T00:00:00Z",
                                                            "to_at": "2026-12-01T00:00:00Z",
                                                            "take": null
                                                        }
                                                    ],
                                                    "blackout_window_ids": []
                                                },
                                                "created_at": "2026-05-18T10:05:00Z",
                                                "updated_at": "2026-05-18T10:05:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-mcp-tools": [
                    "get_plan"
                ]
            },
            "patch": {
                "operationId": "v1.plans.update",
                "description": "The same discriminated shape as create, with every field optional. Omit `kind` to keep the plan's current kind; a block you send must match it. Where a cross-field rule needs a value you did not send, the billing cycle behind a lifetime count check, the currency behind the price floor, the eligibility flags behind the exclusivity check, the plan's stored value stands in, so a partial update is validated against the plan it will actually produce.\n\n- `resources` is optional; omitting it preserves the existing links, sending it replaces them.\n- Every update of a plan on sale queues its push to the payment methods that keep a product catalogue, so a changed price or name reaches Stripe, PayPal, CoinPayments and Razorpay within a minute.\n- `sales_cap` may be set, raised, lowered or cleared with `null`; any change restarts `sales_cap_sold` at `0`.\n- `pass.slots` **replaces** the whole schedule and rebuilds unsold future windows; `pass.windows` **adds** dated windows and never replaces.\n- Setting an active plan's `price` to `0` on a Free account is refused; editing a zero-priced plan that is **off sale** is allowed on any account.\n- `sales_cap_sold`, `position` and `paused` are read-only.\n\nAnswers `200` with the whole plan after the change.",
                "summary": "Update a plan",
                "tags": [
                    "Plans"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "plan",
                        "in": "path",
                        "required": true,
                        "description": "The plan, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdatePlanRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The plan after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PlanResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: when the change needs an entitlement the project owner's account lacks, such as passes on a plan without them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when a block does not match the plan's kind, `name` is taken by another live plan, `price` is below the minimum or is `0` on an active plan of a Free account, two eligibility flags end up set, or a per-kind rule is broken; `error.fields` names the key.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:update"
                ],
                "x-webhook-events": [
                    "plan.updated"
                ],
                "x-mcp-tools": [
                    "update_plan"
                ]
            },
            "delete": {
                "operationId": "v1.plans.destroy",
                "description": "Removes the plan and emits `plan.deleted` with a snapshot taken before the row disappears. Members who already hold it keep their access until it runs out; to stop selling while keeping the plan on the books, unpublish it instead. A pass or series plan is refused while a customer still holds an unfinished window on it, because deleting it would cascade away access that was paid for.",
                "summary": "Delete a plan",
                "tags": [
                    "Plans"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "plan",
                        "in": "path",
                        "required": true,
                        "description": "The plan, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "500": {
                        "description": "`INTERNAL_SERVER_ERROR`: when a customer still holds an unfinished window on the plan; `error.message` says so. Cancel or wait out the windows first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "INTERNAL_SERVER_ERROR": {
                                        "summary": "INTERNAL_SERVER_ERROR",
                                        "value": {
                                            "error": {
                                                "code": "INTERNAL_SERVER_ERROR",
                                                "message": "An unexpected error occurred. The incident has been recorded.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#internal-server-error",
                                                "remediation": "Capture the error.request_id and contact support if the problem persists.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:delete"
                ],
                "x-webhook-events": [
                    "plan.deleted"
                ],
                "x-mcp-tools": [
                    "delete_plan"
                ]
            }
        },
        "/v1/projects/{project}/plans/{plan}/publish": {
            "post": {
                "operationId": "v1.plans.publish",
                "description": "Puts the plan on sale: `active` becomes `true`, `sales_cap_sold` restarts at `0`, and `plan.activated` fires. Publishing also queues the push of the plan to the payment methods that keep a product catalogue (Stripe, PayPal, CoinPayments, Razorpay), the same push a create or update of a plan on sale queues, so a plan created as a draft is sellable through them within a minute of going on sale. A plan that is already on sale is answered as it is and emits nothing. Answers `200` with the plan.",
                "summary": "Publish a plan",
                "tags": [
                    "Plans"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "plan",
                        "in": "path",
                        "required": true,
                        "description": "The plan, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The plan, active.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PlanResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: when the plan is priced at `0` and the project owner's account cannot sell a free plan, or when it is a pass or series and the account lacks Time-Limited Passes.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:update"
                ],
                "x-webhook-events": [
                    "plan.activated"
                ],
                "x-mcp-tools": [
                    "publish_plan"
                ]
            }
        },
        "/v1/projects/{project}/plans/{plan}/unpublish": {
            "post": {
                "operationId": "v1.plans.unpublish",
                "description": "Takes the plan off sale: `active` becomes `false` and `plan.deactivated` fires. Members who already joined keep their access; the plan stays fully editable and can be published again. A plan that is already off sale is answered as it is and emits nothing. Answers `200` with the plan.",
                "summary": "Unpublish a plan",
                "tags": [
                    "Plans"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "plan",
                        "in": "path",
                        "required": true,
                        "description": "The plan, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The plan, inactive.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PlanResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:update"
                ],
                "x-webhook-events": [
                    "plan.deactivated"
                ],
                "x-mcp-tools": [
                    "publish_plan"
                ]
            }
        },
        "/v1/projects/{project}/plans/order": {
            "post": {
                "operationId": "v1.plans.reorder",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/plans/order \\\n  -H \"Authorization: Bearer sbt_...\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"plan_ids\": [\"c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b\", \"b1a7c3d5-2e48-4f60-9a1b-7c5d3e820f94\"]}'\n```\n\nPins the order plans appear in on the public portal and in the bot; `plan_ids` is every plan you want pinned, first to last. Plans left out keep the built-in order (passes, then seasons, then subscriptions, cheapest first) after the pinned ones. Send an empty `plan_ids` to clear every pin. Answers `200` with the project's active plans in their new order, each in the same shape as a read, with `position` set on the pinned ones. The same list produces the same order and one `plan.order_changed` event per call.",
                "summary": "Arrange the storefront order",
                "tags": [
                    "Plans"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ReorderPlansRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Array of `PlanResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "$ref": "#/components/schemas/PlanResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when a plan id belongs to another project, is repeated, or the list exceeds 200 entries; `error.fields` names the entry.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:update"
                ],
                "x-webhook-events": [
                    "plan.order_changed"
                ],
                "x-mcp-tools": [
                    "reorder_plans"
                ]
            }
        },
        "/v1/projects/{project}/plans/{plan}/successor": {
            "post": {
                "operationId": "v1.plans.successor",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/plans/$SERIES_PLAN/successor \\\n  -H \"Authorization: Bearer sbt_...\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nThe plan list's \"start next season\" button. For a `kind: pass_series` plan only: creates a **new** `pass_series` plan copied from the one named, its price, currency, description, eligibility, linked resources, overlap rule, sales cutoff and seat cap, with two deliberate differences: it is created **inactive**, and its slate is **empty**, because a season that went straight on sale with last year's dates would be selling something that has already happened. Rules are carried forward with their date bounds shifted by the length of the finished season; the slate itself and any blackouts are not, since both name windows that have run.\n\nThe old season's `successor_plan_id` is pointed at the new plan (and a presale window is set if the old season had none), which is what lets current holders be offered the next season first. Answers `201` with the new plan in the same discriminated shape as any other read and emits `plan.created` for it. Compose it with a `PATCH` (`pass_series.window_ids` or `pass_series.rules`) and put it on sale with publish.\n\n> **Not idempotent across calls. Call it once per season.** Every call creates another plan, named after the source with a season number appended, and re-points the old season's successor at the newest one. Read the source plan first: if `pass_series.successor_plan_id` is already set, the next season exists. The `Idempotency-Key` protects a retry of the same call, not a second call with a new key.",
                "summary": "Start the next season",
                "tags": [
                    "Plans"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "plan",
                        "in": "path",
                        "required": true,
                        "description": "The finished season, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "201": {
                        "description": "The new season, 201, inactive with an empty slate.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PlanResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the plan is not a pass series; `error.context.plan_id` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:create"
                ],
                "x-webhook-events": [
                    "plan.created"
                ],
                "x-mcp-tools": [
                    "start_next_season"
                ]
            }
        },
        "/v1/projects/{project}/portal-design": {
            "get": {
                "operationId": "v1.portal-design.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/portal-design \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe published document, the draft when there is one, when each last moved, and a fresh preview address, or null for a project without a handle. Every key of the fourteen sections comes back in the stored shape `PUT` takes, so a design read here can be changed and sent back. `draft` is `null` and `has_draft` false while nothing is drafted.",
                "summary": "Get a project's portal design",
                "tags": [
                    "Portal Design"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The published design, the draft and the preview address.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PortalDesignResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "published": {
                                                    "preset": "midnight",
                                                    "color_mode": "light",
                                                    "accent": "#22d3ee",
                                                    "accent_secondary": null,
                                                    "background": "#0f172a",
                                                    "grid": true,
                                                    "surface": "#1e293b",
                                                    "text": "#cbd5e1",
                                                    "heading": "#f8fafc",
                                                    "muted": "#94a3b8",
                                                    "tagline": "Weekly research notes and the members lounge",
                                                    "social_links": [],
                                                    "font_display": "space-grotesk",
                                                    "font_body": "inter",
                                                    "heading_case": "uppercase",
                                                    "type_scale": "regular",
                                                    "radius": "round",
                                                    "button_style": "pill",
                                                    "button_fill": "dark",
                                                    "button_case": "uppercase",
                                                    "shadow": "strong",
                                                    "card_border": false,
                                                    "arrangement": "sidebar_left",
                                                    "content_width": "regular",
                                                    "sticky_sidebar": true,
                                                    "plan_grid": "list",
                                                    "plan_density": "roomy",
                                                    "plans_heading": true,
                                                    "metrics_subscribers": true,
                                                    "metrics_followers": true,
                                                    "metrics_threshold": 0,
                                                    "plans_title": null,
                                                    "plans_subtitle": null,
                                                    "label_login": null,
                                                    "label_share": null,
                                                    "label_subscribe": null,
                                                    "checkout_title": null,
                                                    "checkout_subtitle": null,
                                                    "checkout_note": null,
                                                    "success_title": null,
                                                    "success_message": null,
                                                    "perks_title": null,
                                                    "perks": [],
                                                    "faq_title": null,
                                                    "faq": [],
                                                    "about_name": null,
                                                    "about_bio": null,
                                                    "custom_button_label": null,
                                                    "custom_button_url": null,
                                                    "footer_refund_url": null,
                                                    "footer_contact_url": null,
                                                    "footer_imprint_url": null,
                                                    "footer_line": null,
                                                    "footer_help": true,
                                                    "announcement_text": null,
                                                    "announcement_url": null,
                                                    "announcement_starts_at": null,
                                                    "announcement_ends_at": null,
                                                    "video_url": null,
                                                    "gallery_title": null,
                                                    "gallery": [],
                                                    "testimonials_title": null,
                                                    "testimonials": [],
                                                    "sidebar_items": [
                                                        {
                                                            "key": "tagline",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "metrics",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "buttons",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "description",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "social_links",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "footer",
                                                            "shown": true
                                                        }
                                                    ],
                                                    "content_blocks": [
                                                        {
                                                            "key": "perks",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "about",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "faq",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "video",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "gallery",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "testimonials",
                                                            "shown": true
                                                        }
                                                    ],
                                                    "locale_switcher": true,
                                                    "featured_plan_id": null,
                                                    "coupon_box": "always",
                                                    "share_button": true,
                                                    "share_networks": [
                                                        "bluesky",
                                                        "buffer",
                                                        "email",
                                                        "facebook",
                                                        "flipboard",
                                                        "line",
                                                        "linkedin",
                                                        "mix",
                                                        "pinterest",
                                                        "reddit",
                                                        "telegram",
                                                        "threads",
                                                        "tumblr",
                                                        "x",
                                                        "vk",
                                                        "whatsapp",
                                                        "xing"
                                                    ],
                                                    "login_button": true,
                                                    "social_proof": false,
                                                    "seats_badges": true,
                                                    "seo_indexable": true,
                                                    "seo_social_card": true,
                                                    "pixel_meta": null,
                                                    "pixel_ga4": null,
                                                    "pixel_tiktok": null,
                                                    "pixel_google_ads": null,
                                                    "custom_css": null,
                                                    "seo_title_suffix": null,
                                                    "seo_description": null,
                                                    "social_card_url": null,
                                                    "default_locale": null,
                                                    "locales": [
                                                        "en",
                                                        "fr",
                                                        "es",
                                                        "it",
                                                        "hi",
                                                        "bn",
                                                        "de",
                                                        "pt",
                                                        "tr",
                                                        "si"
                                                    ]
                                                },
                                                "draft": null,
                                                "has_draft": false,
                                                "draft_updated_at": null,
                                                "published_at": "2026-10-26T16:40:08+00:00",
                                                "preview_url": "https://my.subscriby.net/research-premium?preview=7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13&expires=1793032000&signature=9c1d…"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project:view"
                ],
                "x-mcp-tools": [
                    "get_portal_design"
                ]
            },
            "put": {
                "operationId": "v1.portal-design.update",
                "description": "```bash\ncurl -X PUT https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/portal-design \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: 7c1f0d3a-6b2e-4f88-9a41-2d5e6c7b8a90\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"preset\": \"midnight\", \"accent\": \"#22d3ee\", \"font_display\": \"space-grotesk\"}'\n```\n\nChanges the keys sent in the draft, starting one from the published design when none exists; every key is optional and an omitted one keeps its drafted value. Members keep seeing the published design until `publish`. Pictures are stored first through the images endpoint and their addresses written into `gallery`, a quote's `avatar_url` or `social_card_url`.",
                "summary": "Save portal design changes",
                "tags": [
                    "Portal Design"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdatePortalDesignRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The design after the change, the draft among it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PortalDesignResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "published": {
                                                    "preset": "classic",
                                                    "color_mode": "light",
                                                    "accent": "#f43f5e",
                                                    "accent_secondary": null,
                                                    "background": "#e4e4e7",
                                                    "grid": true,
                                                    "surface": "#ffffff",
                                                    "text": "#27272a",
                                                    "heading": "#18181b",
                                                    "muted": "#71717a",
                                                    "tagline": "Weekly research notes and the members lounge",
                                                    "social_links": [],
                                                    "font_display": "asap-condensed",
                                                    "font_body": "inter",
                                                    "heading_case": "uppercase",
                                                    "type_scale": "regular",
                                                    "radius": "round",
                                                    "button_style": "pill",
                                                    "button_fill": "dark",
                                                    "button_case": "uppercase",
                                                    "shadow": "strong",
                                                    "card_border": false,
                                                    "arrangement": "sidebar_left",
                                                    "content_width": "regular",
                                                    "sticky_sidebar": true,
                                                    "plan_grid": "list",
                                                    "plan_density": "roomy",
                                                    "plans_heading": true,
                                                    "metrics_subscribers": true,
                                                    "metrics_followers": true,
                                                    "metrics_threshold": 0,
                                                    "plans_title": null,
                                                    "plans_subtitle": null,
                                                    "label_login": null,
                                                    "label_share": null,
                                                    "label_subscribe": null,
                                                    "checkout_title": null,
                                                    "checkout_subtitle": null,
                                                    "checkout_note": null,
                                                    "success_title": null,
                                                    "success_message": null,
                                                    "perks_title": null,
                                                    "perks": [],
                                                    "faq_title": null,
                                                    "faq": [],
                                                    "about_name": null,
                                                    "about_bio": null,
                                                    "custom_button_label": null,
                                                    "custom_button_url": null,
                                                    "footer_refund_url": null,
                                                    "footer_contact_url": null,
                                                    "footer_imprint_url": null,
                                                    "footer_line": null,
                                                    "footer_help": true,
                                                    "announcement_text": null,
                                                    "announcement_url": null,
                                                    "announcement_starts_at": null,
                                                    "announcement_ends_at": null,
                                                    "video_url": null,
                                                    "gallery_title": null,
                                                    "gallery": [],
                                                    "testimonials_title": null,
                                                    "testimonials": [],
                                                    "sidebar_items": [
                                                        {
                                                            "key": "tagline",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "metrics",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "buttons",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "description",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "social_links",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "footer",
                                                            "shown": true
                                                        }
                                                    ],
                                                    "content_blocks": [
                                                        {
                                                            "key": "perks",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "about",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "faq",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "video",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "gallery",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "testimonials",
                                                            "shown": true
                                                        }
                                                    ],
                                                    "locale_switcher": true,
                                                    "featured_plan_id": null,
                                                    "coupon_box": "always",
                                                    "share_button": true,
                                                    "share_networks": [
                                                        "bluesky",
                                                        "buffer",
                                                        "email",
                                                        "facebook",
                                                        "flipboard",
                                                        "line",
                                                        "linkedin",
                                                        "mix",
                                                        "pinterest",
                                                        "reddit",
                                                        "telegram",
                                                        "threads",
                                                        "tumblr",
                                                        "x",
                                                        "vk",
                                                        "whatsapp",
                                                        "xing"
                                                    ],
                                                    "login_button": true,
                                                    "social_proof": false,
                                                    "seats_badges": true,
                                                    "seo_indexable": true,
                                                    "seo_social_card": true,
                                                    "pixel_meta": null,
                                                    "pixel_ga4": null,
                                                    "pixel_tiktok": null,
                                                    "pixel_google_ads": null,
                                                    "custom_css": null,
                                                    "seo_title_suffix": null,
                                                    "seo_description": null,
                                                    "social_card_url": null,
                                                    "default_locale": null,
                                                    "locales": [
                                                        "en",
                                                        "fr",
                                                        "es",
                                                        "it",
                                                        "hi",
                                                        "bn",
                                                        "de",
                                                        "pt",
                                                        "tr",
                                                        "si"
                                                    ]
                                                },
                                                "draft": {
                                                    "preset": "midnight",
                                                    "color_mode": "light",
                                                    "accent": "#22d3ee",
                                                    "accent_secondary": null,
                                                    "background": "#0f172a",
                                                    "grid": true,
                                                    "surface": "#1e293b",
                                                    "text": "#cbd5e1",
                                                    "heading": "#f8fafc",
                                                    "muted": "#94a3b8",
                                                    "tagline": "Weekly research notes and the members lounge",
                                                    "social_links": [],
                                                    "font_display": "space-grotesk",
                                                    "font_body": "inter",
                                                    "heading_case": "uppercase",
                                                    "type_scale": "regular",
                                                    "radius": "round",
                                                    "button_style": "pill",
                                                    "button_fill": "dark",
                                                    "button_case": "uppercase",
                                                    "shadow": "strong",
                                                    "card_border": false,
                                                    "arrangement": "sidebar_left",
                                                    "content_width": "regular",
                                                    "sticky_sidebar": true,
                                                    "plan_grid": "list",
                                                    "plan_density": "roomy",
                                                    "plans_heading": true,
                                                    "metrics_subscribers": true,
                                                    "metrics_followers": true,
                                                    "metrics_threshold": 0,
                                                    "plans_title": null,
                                                    "plans_subtitle": null,
                                                    "label_login": null,
                                                    "label_share": null,
                                                    "label_subscribe": null,
                                                    "checkout_title": null,
                                                    "checkout_subtitle": null,
                                                    "checkout_note": null,
                                                    "success_title": null,
                                                    "success_message": null,
                                                    "perks_title": null,
                                                    "perks": [],
                                                    "faq_title": null,
                                                    "faq": [],
                                                    "about_name": null,
                                                    "about_bio": null,
                                                    "custom_button_label": null,
                                                    "custom_button_url": null,
                                                    "footer_refund_url": null,
                                                    "footer_contact_url": null,
                                                    "footer_imprint_url": null,
                                                    "footer_line": null,
                                                    "footer_help": true,
                                                    "announcement_text": null,
                                                    "announcement_url": null,
                                                    "announcement_starts_at": null,
                                                    "announcement_ends_at": null,
                                                    "video_url": null,
                                                    "gallery_title": null,
                                                    "gallery": [],
                                                    "testimonials_title": null,
                                                    "testimonials": [],
                                                    "sidebar_items": [
                                                        {
                                                            "key": "tagline",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "metrics",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "buttons",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "description",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "social_links",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "footer",
                                                            "shown": true
                                                        }
                                                    ],
                                                    "content_blocks": [
                                                        {
                                                            "key": "perks",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "about",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "faq",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "video",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "gallery",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "testimonials",
                                                            "shown": true
                                                        }
                                                    ],
                                                    "locale_switcher": true,
                                                    "featured_plan_id": null,
                                                    "coupon_box": "always",
                                                    "share_button": true,
                                                    "share_networks": [
                                                        "bluesky",
                                                        "buffer",
                                                        "email",
                                                        "facebook",
                                                        "flipboard",
                                                        "line",
                                                        "linkedin",
                                                        "mix",
                                                        "pinterest",
                                                        "reddit",
                                                        "telegram",
                                                        "threads",
                                                        "tumblr",
                                                        "x",
                                                        "vk",
                                                        "whatsapp",
                                                        "xing"
                                                    ],
                                                    "login_button": true,
                                                    "social_proof": false,
                                                    "seats_badges": true,
                                                    "seo_indexable": true,
                                                    "seo_social_card": true,
                                                    "pixel_meta": null,
                                                    "pixel_ga4": null,
                                                    "pixel_tiktok": null,
                                                    "pixel_google_ads": null,
                                                    "custom_css": null,
                                                    "seo_title_suffix": null,
                                                    "seo_description": null,
                                                    "social_card_url": null,
                                                    "default_locale": null,
                                                    "locales": [
                                                        "en",
                                                        "fr",
                                                        "es",
                                                        "it",
                                                        "hi",
                                                        "bn",
                                                        "de",
                                                        "pt",
                                                        "tr",
                                                        "si"
                                                    ]
                                                },
                                                "has_draft": true,
                                                "draft_updated_at": "2026-10-26T16:12:45+00:00",
                                                "published_at": "2026-10-20T09:30:00+00:00",
                                                "preview_url": "https://my.subscriby.net/research-premium?preview=7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13&expires=1793030400&signature=4b8f…"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TOKEN_MISSING_ABILITY`: when the token lacks `project:update`, or its owner's role on the project's team may not change the project.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when a key is unknown, a value has the wrong type, or a value is not one the portal can draw: a colour that is not hex, a text colour that blends into the surface or the background, a plan the project lacks as `featured_plan_id`, a list past its ceiling, `locales` without `default_locale`, a stylesheet that would load or run, an announcement that ends before it starts. The message names the key.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project:update"
                ],
                "x-mcp-tools": [
                    "update_portal_design"
                ]
            }
        },
        "/v1/projects/{project}/portal-design/publish": {
            "post": {
                "operationId": "v1.portal-design.publish",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/portal-design/publish \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: 9e2b4c6d-1a3f-4e5b-8c7d-0f1a2b3c4d5e\"\n```\n\nMakes the draft the design members see; the portal, the plan embed and the social card paint with it on their next render, and `project.design_published` is emitted naming the sections that changed. Answers the design with no draft left.",
                "summary": "Publish the portal design",
                "tags": [
                    "Portal Design"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The design, published, with no draft left.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PortalDesignResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "published": {
                                                    "preset": "midnight",
                                                    "color_mode": "light",
                                                    "accent": "#22d3ee",
                                                    "accent_secondary": null,
                                                    "background": "#0f172a",
                                                    "grid": true,
                                                    "surface": "#1e293b",
                                                    "text": "#cbd5e1",
                                                    "heading": "#f8fafc",
                                                    "muted": "#94a3b8",
                                                    "tagline": "Weekly research notes and the members lounge",
                                                    "social_links": [],
                                                    "font_display": "space-grotesk",
                                                    "font_body": "inter",
                                                    "heading_case": "uppercase",
                                                    "type_scale": "regular",
                                                    "radius": "round",
                                                    "button_style": "pill",
                                                    "button_fill": "dark",
                                                    "button_case": "uppercase",
                                                    "shadow": "strong",
                                                    "card_border": false,
                                                    "arrangement": "sidebar_left",
                                                    "content_width": "regular",
                                                    "sticky_sidebar": true,
                                                    "plan_grid": "list",
                                                    "plan_density": "roomy",
                                                    "plans_heading": true,
                                                    "metrics_subscribers": true,
                                                    "metrics_followers": true,
                                                    "metrics_threshold": 0,
                                                    "plans_title": null,
                                                    "plans_subtitle": null,
                                                    "label_login": null,
                                                    "label_share": null,
                                                    "label_subscribe": null,
                                                    "checkout_title": null,
                                                    "checkout_subtitle": null,
                                                    "checkout_note": null,
                                                    "success_title": null,
                                                    "success_message": null,
                                                    "perks_title": null,
                                                    "perks": [],
                                                    "faq_title": null,
                                                    "faq": [],
                                                    "about_name": null,
                                                    "about_bio": null,
                                                    "custom_button_label": null,
                                                    "custom_button_url": null,
                                                    "footer_refund_url": null,
                                                    "footer_contact_url": null,
                                                    "footer_imprint_url": null,
                                                    "footer_line": null,
                                                    "footer_help": true,
                                                    "announcement_text": null,
                                                    "announcement_url": null,
                                                    "announcement_starts_at": null,
                                                    "announcement_ends_at": null,
                                                    "video_url": null,
                                                    "gallery_title": null,
                                                    "gallery": [],
                                                    "testimonials_title": null,
                                                    "testimonials": [],
                                                    "sidebar_items": [
                                                        {
                                                            "key": "tagline",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "metrics",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "buttons",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "description",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "social_links",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "footer",
                                                            "shown": true
                                                        }
                                                    ],
                                                    "content_blocks": [
                                                        {
                                                            "key": "perks",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "about",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "faq",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "video",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "gallery",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "testimonials",
                                                            "shown": true
                                                        }
                                                    ],
                                                    "locale_switcher": true,
                                                    "featured_plan_id": null,
                                                    "coupon_box": "always",
                                                    "share_button": true,
                                                    "share_networks": [
                                                        "bluesky",
                                                        "buffer",
                                                        "email",
                                                        "facebook",
                                                        "flipboard",
                                                        "line",
                                                        "linkedin",
                                                        "mix",
                                                        "pinterest",
                                                        "reddit",
                                                        "telegram",
                                                        "threads",
                                                        "tumblr",
                                                        "x",
                                                        "vk",
                                                        "whatsapp",
                                                        "xing"
                                                    ],
                                                    "login_button": true,
                                                    "social_proof": false,
                                                    "seats_badges": true,
                                                    "seo_indexable": true,
                                                    "seo_social_card": true,
                                                    "pixel_meta": null,
                                                    "pixel_ga4": null,
                                                    "pixel_tiktok": null,
                                                    "pixel_google_ads": null,
                                                    "custom_css": null,
                                                    "seo_title_suffix": null,
                                                    "seo_description": null,
                                                    "social_card_url": null,
                                                    "default_locale": null,
                                                    "locales": [
                                                        "en",
                                                        "fr",
                                                        "es",
                                                        "it",
                                                        "hi",
                                                        "bn",
                                                        "de",
                                                        "pt",
                                                        "tr",
                                                        "si"
                                                    ]
                                                },
                                                "draft": null,
                                                "has_draft": false,
                                                "draft_updated_at": null,
                                                "published_at": "2026-10-26T16:40:08+00:00",
                                                "preview_url": "https://my.subscriby.net/research-premium?preview=7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13&expires=1793032000&signature=9c1d…"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TOKEN_MISSING_ABILITY`: when the token lacks `project:update`, or its owner's role on the project's team may not change the project.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when nothing is drafted.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project:update"
                ],
                "x-webhook-events": [
                    "project.design_published"
                ],
                "x-mcp-tools": [
                    "publish_portal_design"
                ]
            }
        },
        "/v1/projects/{project}/portal-design/discard": {
            "post": {
                "operationId": "v1.portal-design.discard",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/portal-design/discard \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: 5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d\"\n```\n\nThrows the draft away and keeps what members see; a picture only the draft named is removed with it. Answers the design, the published document alone.",
                "summary": "Discard the portal design draft",
                "tags": [
                    "Portal Design"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The design, the published document alone.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PortalDesignResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "published": {
                                                    "preset": "midnight",
                                                    "color_mode": "light",
                                                    "accent": "#22d3ee",
                                                    "accent_secondary": null,
                                                    "background": "#0f172a",
                                                    "grid": true,
                                                    "surface": "#1e293b",
                                                    "text": "#cbd5e1",
                                                    "heading": "#f8fafc",
                                                    "muted": "#94a3b8",
                                                    "tagline": "Weekly research notes and the members lounge",
                                                    "social_links": [],
                                                    "font_display": "space-grotesk",
                                                    "font_body": "inter",
                                                    "heading_case": "uppercase",
                                                    "type_scale": "regular",
                                                    "radius": "round",
                                                    "button_style": "pill",
                                                    "button_fill": "dark",
                                                    "button_case": "uppercase",
                                                    "shadow": "strong",
                                                    "card_border": false,
                                                    "arrangement": "sidebar_left",
                                                    "content_width": "regular",
                                                    "sticky_sidebar": true,
                                                    "plan_grid": "list",
                                                    "plan_density": "roomy",
                                                    "plans_heading": true,
                                                    "metrics_subscribers": true,
                                                    "metrics_followers": true,
                                                    "metrics_threshold": 0,
                                                    "plans_title": null,
                                                    "plans_subtitle": null,
                                                    "label_login": null,
                                                    "label_share": null,
                                                    "label_subscribe": null,
                                                    "checkout_title": null,
                                                    "checkout_subtitle": null,
                                                    "checkout_note": null,
                                                    "success_title": null,
                                                    "success_message": null,
                                                    "perks_title": null,
                                                    "perks": [],
                                                    "faq_title": null,
                                                    "faq": [],
                                                    "about_name": null,
                                                    "about_bio": null,
                                                    "custom_button_label": null,
                                                    "custom_button_url": null,
                                                    "footer_refund_url": null,
                                                    "footer_contact_url": null,
                                                    "footer_imprint_url": null,
                                                    "footer_line": null,
                                                    "footer_help": true,
                                                    "announcement_text": null,
                                                    "announcement_url": null,
                                                    "announcement_starts_at": null,
                                                    "announcement_ends_at": null,
                                                    "video_url": null,
                                                    "gallery_title": null,
                                                    "gallery": [],
                                                    "testimonials_title": null,
                                                    "testimonials": [],
                                                    "sidebar_items": [
                                                        {
                                                            "key": "tagline",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "metrics",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "buttons",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "description",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "social_links",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "footer",
                                                            "shown": true
                                                        }
                                                    ],
                                                    "content_blocks": [
                                                        {
                                                            "key": "perks",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "about",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "faq",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "video",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "gallery",
                                                            "shown": true
                                                        },
                                                        {
                                                            "key": "testimonials",
                                                            "shown": true
                                                        }
                                                    ],
                                                    "locale_switcher": true,
                                                    "featured_plan_id": null,
                                                    "coupon_box": "always",
                                                    "share_button": true,
                                                    "share_networks": [
                                                        "bluesky",
                                                        "buffer",
                                                        "email",
                                                        "facebook",
                                                        "flipboard",
                                                        "line",
                                                        "linkedin",
                                                        "mix",
                                                        "pinterest",
                                                        "reddit",
                                                        "telegram",
                                                        "threads",
                                                        "tumblr",
                                                        "x",
                                                        "vk",
                                                        "whatsapp",
                                                        "xing"
                                                    ],
                                                    "login_button": true,
                                                    "social_proof": false,
                                                    "seats_badges": true,
                                                    "seo_indexable": true,
                                                    "seo_social_card": true,
                                                    "pixel_meta": null,
                                                    "pixel_ga4": null,
                                                    "pixel_tiktok": null,
                                                    "pixel_google_ads": null,
                                                    "custom_css": null,
                                                    "seo_title_suffix": null,
                                                    "seo_description": null,
                                                    "social_card_url": null,
                                                    "default_locale": null,
                                                    "locales": [
                                                        "en",
                                                        "fr",
                                                        "es",
                                                        "it",
                                                        "hi",
                                                        "bn",
                                                        "de",
                                                        "pt",
                                                        "tr",
                                                        "si"
                                                    ]
                                                },
                                                "draft": null,
                                                "has_draft": false,
                                                "draft_updated_at": null,
                                                "published_at": "2026-10-26T16:40:08+00:00",
                                                "preview_url": "https://my.subscriby.net/research-premium?preview=7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13&expires=1793032000&signature=9c1d…"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TOKEN_MISSING_ABILITY`: when the token lacks `project:update`, or its owner's role on the project's team may not change the project.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when nothing is drafted.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project:update"
                ],
                "x-mcp-tools": [
                    "discard_portal_design_draft"
                ]
            }
        },
        "/v1/projects/{project}/portal-design/images/{slot}": {
            "post": {
                "operationId": "v1.portal-design.images.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/portal-design/images/gallery \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: 1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e\" \\\n  -F \"image=@lounge.jpg\"\n```\n\nStores a picture for the design, cut from the centre to the slot's size: `gallery` to 1200 by 800, `avatar` to 160 by 160, `card` to 1200 by 630. The answer carries the address to write into the design with `PUT`; a picture nothing names any longer is removed on the next save, publish or discard. The banner and the project photo are not slots here; they live on the project.",
                "summary": "Store a portal design picture",
                "tags": [
                    "Portal Design"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "slot",
                        "in": "path",
                        "required": true,
                        "description": "The slot the picture is for: `gallery`, `avatar` or `card`; it sets the size.",
                        "schema": {
                            "$ref": "#/components/schemas/PortalImageSlot"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/UploadPortalDesignImageRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The stored picture with its address.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/PortalImageResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "slot": "gallery",
                                                "url": "https://static.subscriby.net/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/portal/gallery_1761495608_k3m9qa.jpg",
                                                "width": 1200,
                                                "height": 800
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TOKEN_MISSING_ABILITY`: when the token lacks `project:update`, or its owner's role on the project's team may not change the project.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: when `slot` is not `gallery`, `avatar` or `card`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `image` is missing, not a JPG, PNG, GIF or WEBP picture, or over 5 MB.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project:update"
                ]
            }
        },
        "/v1/projects": {
            "get": {
                "operationId": "v1.projects.index",
                "description": "```bash\ncurl https://api.subscriby.net/v1/projects \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nEvery project visible to the token, newest first, paged with `page` and `per_page` (default 25). A token minted with `scope:project:<uuid>` entries lists only those projects.",
                "summary": "List projects",
                "tags": [
                    "Projects"
                ],
                "parameters": [
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page, newest first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/ProjectResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project:view-any"
                ],
                "x-mcp-tools": [
                    "list_projects"
                ]
            },
            "post": {
                "operationId": "v1.projects.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Research Premium\",\n    \"description\": \"Weekly deep-dive research notes.\",\n    \"handle\": \"research-premium\"\n  }'\n```\n\nBanner and photo are optional image uploads. Send `multipart/form-data` when you want the API to accept the raw image:\n\n```bash\ncurl -X POST https://api.subscriby.net/v1/projects \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -F \"name=Research Premium\" \\\n  -F \"description=Weekly deep-dive research notes.\" \\\n  -F \"banner=@./banner.jpg\" \\\n  -F \"photo=@./avatar.jpg\"\n```\n\nAnswers `201` with the project and emits `project.created`. Creating a project enforces the creator's tier project limit; exceeding it is `403 TEAM_TIER_REQUIRED` with a `required_capability` hint in `error.context`.\n\n### Validation rules\n\nEnforced on both create and update (every field is optional on update):\n\n- `name`: required on create. String, 5–255 characters.\n- `description`: optional. String, max 1,000 characters. HTML is filtered to a safe subset before storage.\n- `terms`, `privacy`: optional. URLs, max 255 characters each.\n- `banner`, `photo`: optional. Image uploads, max **5 MB** each, sent as `multipart/form-data`.\n- `handle`: optional, on every tier. Lowercase alpha-dash ASCII, 5–255 characters, unique across every project's current and former handles. Omitted, a random handle is assigned; it can be changed later, and every former handle keeps redirecting to the current one.\n- `active`: optional boolean.\n- `storefront_arrangement`: optional, `manual` or `live`. `live` is refused with `TEAM_TIER_REQUIRED` when the project owner's plan or addons do not include time-limited passes; `manual` is always accepted.\n- `outage_compensations`: optional boolean, `true` on every new project. **Outage Compensation**: when a platform refuses the project's connector for an hour or more and later answers again, every member whose paid access overlapped the gap gets the lost time added to the end of their access automatically, so nobody pays for days they could not use. Set it to `false` when the creator would rather settle outages themselves, for example with refunds or coupons. See [Connector outages](https://docs.subscriby.net/disaster-recovery/connector-outages).\n- `team_id`: optional UUID; must be a team the token's owner belongs to. Defaults to the token's scoped team.\n\n> **Artwork is processed after the request.** The response body returns the project's metadata only, not the hosted image URLs. Image processing (resize, re-encode, upload to storage) runs on the server after a successful create or update; clients that need the hosted URL should fetch the project once upload is complete.",
                "summary": "Create a project",
                "tags": [
                    "Projects"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreProjectRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The new project.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ProjectResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                                "user_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "name": "Research Premium",
                                                "handle": "research-premium",
                                                "description": "Weekly deep-dive research notes.",
                                                "terms": null,
                                                "privacy": null,
                                                "banner_url": null,
                                                "photo_url": null,
                                                "outage_compensations": true,
                                                "active": true,
                                                "created_at": "2026-05-18T10:05:00Z",
                                                "updated_at": "2026-05-18T10:05:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: when the creator's tier project limit is reached, or `hide_branding` is `true` on a tier that keeps the mark; `error.context.required_capability` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: with per-field messages under `error.fields`, a handle another project has or used to have among them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project:create"
                ],
                "x-webhook-events": [
                    "project.created"
                ],
                "x-mcp-tools": [
                    "create_project"
                ]
            }
        },
        "/v1/projects/{project}": {
            "get": {
                "operationId": "v1.projects.show",
                "description": "One project. A project outside the token's team or its project scope is `404 RESOURCE_NOT_FOUND`.\n\n`outage_compensations` is the project's **Outage Compensation** switch, `terms` and `privacy` the URLs members are asked to accept, and `banner_url` / `photo_url` the hosted artwork (null until uploaded). `storefront_arrangement` says how the portal, the embed and the bot order the plans on offer: `manual` is the order pinned through [Arrange the storefront order](https://docs.subscriby.net/api/v1/reference/plans/arrange-the-storefront-order), with passes, seasons and then subscriptions, cheapest first, behind anything unpinned; `live` puts the passes and seasons whose access is on now first, the one ending soonest at the top, then those opening soonest, then everything else in the pinned order, so a creator selling dated passes never has to re-arrange. `live` needs the owner's time-limited passes capability (Growth, or the Passes Addon on any plan): setting it without one is refused with `TEAM_TIER_REQUIRED`, and when the capability lapses the storefronts fall back to the pinned order at once while the stored value is reset to `manual` with a `project.updated` event. A project has no platform field: it installs [connectors](https://docs.subscriby.net/api/v1/reference/connectors), and the project's connectors list names them. Clients that read a `type` on projects before 5.0 must switch to the connectors list; the field is gone.",
                "summary": "Get a project",
                "tags": [
                    "Projects"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The project.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ProjectResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                                "user_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "name": "Research Premium",
                                                "handle": "research-premium",
                                                "description": "Weekly deep-dive research notes.",
                                                "terms": "https://example.com/terms",
                                                "privacy": "https://example.com/privacy",
                                                "banner_url": "https://static.subscriby.net/projects/7f3d1c92/banner.webp",
                                                "photo_url": "https://static.subscriby.net/projects/7f3d1c92/photo.webp",
                                                "outage_compensations": true,
                                                "active": true,
                                                "created_at": "2026-05-18T10:05:00Z",
                                                "updated_at": "2026-05-18T10:05:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project:view"
                ],
                "x-mcp-tools": [
                    "get_project"
                ]
            },
            "patch": {
                "operationId": "v1.projects.update",
                "description": "Every field is optional; only the fields present in the body change, under the same validation rules as create. Sending a new `handle` moves the portal URL at once, and every address the project answered on before keeps redirecting to the current one; a blank handle switches the portal page off. Answers `200` with the project and emits `project.updated`.",
                "summary": "Update a project",
                "tags": [
                    "Projects"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateProjectRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The project after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ProjectResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: when `hide_branding` is turned on without the capability, or `storefront_arrangement` is set to `live` without time-limited passes.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: with per-field messages under `error.fields`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project:update"
                ],
                "x-webhook-events": [
                    "project.updated"
                ],
                "x-mcp-tools": [
                    "update_project"
                ]
            },
            "delete": {
                "operationId": "v1.projects.destroy",
                "description": "Deletes the project and everything under it. Returns `204 No Content` and emits `project.deleted`. Prefer archiving when you want to pause intake without losing history.",
                "summary": "Delete a project",
                "tags": [
                    "Projects"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project:delete"
                ],
                "x-webhook-events": [
                    "project.deleted"
                ],
                "x-mcp-tools": [
                    "delete_project"
                ]
            }
        },
        "/v1/projects/{project}/archive": {
            "post": {
                "operationId": "v1.projects.archive",
                "description": "Switches the project off: `active` becomes `false`, the portal stops selling, and every plan, member and payment method is kept. Archive and restore are RPC-style actions separate from the update: they preserve the project's data while flipping `active`, so prefer them over delete when you want to pause intake without losing history. Answers `200` with the project and emits `project.archived`. Gated on `project:update`, not `project:delete`, because it flips one column of the project.",
                "summary": "Archive a project",
                "tags": [
                    "Projects"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The project, inactive.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ProjectResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project:update"
                ],
                "x-webhook-events": [
                    "project.archived"
                ],
                "x-mcp-tools": [
                    "archive_project"
                ]
            }
        },
        "/v1/projects/{project}/restore": {
            "post": {
                "operationId": "v1.projects.restore",
                "description": "Switches an archived project back on. Answers `200` with the project and emits `project.restored`.",
                "summary": "Restore a project",
                "tags": [
                    "Projects"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The project, active.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ProjectResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project:update"
                ],
                "x-webhook-events": [
                    "project.restored"
                ],
                "x-mcp-tools": [
                    "restore_project"
                ]
            }
        },
        "/v1/projects/{project}/sequences": {
            "get": {
                "operationId": "v1.sequences.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/sequences?active=true&per_page=25\" \\\n  -H \"Authorization: Bearer sbt_...\"\n```\n\nPages the project's sequences, newest first, each with its steps in order and how it has done: every member ever enrolled, the members still receiving steps, the members who received every step, and the members a payment brought back while they were enrolled. `active` keeps the running or the paused ones; `trigger` keeps one trigger; `sort_by` takes `created_at`, `name` or `updated_at`.",
                "summary": "List a project's sequences",
                "tags": [
                    "Recovery Sequences"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "active",
                        "in": "query",
                        "description": "Keep only running sequences (`true`) or only paused ones (`false`). Omit for both.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "true",
                                "false",
                                "1",
                                "0"
                            ]
                        }
                    },
                    {
                        "name": "trigger",
                        "in": "query",
                        "description": "Keep only the sequences on one trigger: `churned`, `lead`, `stalled_checkout` or `trial_ending`.",
                        "schema": {
                            "$ref": "#/components/schemas/SequenceTrigger"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page of sequences, newest first, each with its steps and its counts.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/SequenceResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-sequence:view-any"
                ],
                "x-mcp-tools": [
                    "list_sequences"
                ]
            },
            "post": {
                "operationId": "v1.sequences.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/sequences \\\n  -H \"Authorization: Bearer sbt_...\" \\\n  -H \"Idempotency-Key: 6b1f0d2e-9c3a-4e8b-b2d1-7a9c5e3f1d04\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\": \"Win-back after churn\", \"steps\": [{\"delay_days\": 3, \"body\": \"Hi {name}, your place in {project} is still here: {link}\"}, {\"delay_days\": 7, \"body\": \"{coupon} takes {discount} off: {link}\", \"coupon_id\": \"3b7c9d1e-5f24-4a86-9c0b-2d4e6f8a1b3c\"}]}'\n```\n\nBuilds the sequence with its steps in one write and answers it with `201`; `trigger` defaults to `churned` and `active` to `true`. Up to 8 steps, the first 0 to 180 days after the trigger (`0` goes out on the next hourly run) and each later one 1 to 180 days after the one before, with a message of 1 to 1,000 characters. A sequence built without steps exists and enrols nobody until it has one.\n\n> The body is sent as a chat message, so a step with a coupon reads best when it uses `{coupon}` and `{discount}`, and every step should end on `{link}`, which is the way back.",
                "summary": "Create a sequence",
                "tags": [
                    "Recovery Sequences"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreSequenceRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The new sequence, `201`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SequenceResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-sequence:create"
                ],
                "x-webhook-events": [
                    "sequence.created"
                ],
                "x-mcp-tools": [
                    "create_sequence"
                ]
            }
        },
        "/v1/projects/{project}/sequences/{sequence}": {
            "get": {
                "operationId": "v1.sequences.show",
                "description": "One sequence with its steps and its counts. A sequence of another project, or one the creator deleted, is `404 RESOURCE_NOT_FOUND`.",
                "summary": "Get a sequence",
                "tags": [
                    "Recovery Sequences"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "sequence",
                        "in": "path",
                        "required": true,
                        "description": "The sequence, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The sequence with its steps and its counts.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SequenceResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "9d2f4b6a-1c3e-4f58-8a7b-6e5d4c3b2a19",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "name": "Win-back after churn",
                                                "trigger": "churned",
                                                "active": true,
                                                "steps": [
                                                    {
                                                        "id": "4e8a2c6d-7b1f-4d93-a5c0-8f2e1b7d6c54",
                                                        "position": 1,
                                                        "delay_days": 3,
                                                        "body": "Hi {name}, your place in {project} is still here whenever you want it back: {link}",
                                                        "coupon": null
                                                    },
                                                    {
                                                        "id": "b1c7e9f3-2a4d-4e86-9b0c-5d7f8a2e1c43",
                                                        "position": 2,
                                                        "delay_days": 7,
                                                        "body": "Still thinking it over? {coupon} takes {discount} off your first month back: {link}",
                                                        "coupon": {
                                                            "id": "3b7c9d1e-5f24-4a86-9c0b-2d4e6f8a1b3c",
                                                            "code": "COMEBACK20"
                                                        }
                                                    }
                                                ],
                                                "counts": {
                                                    "enrolled": 12,
                                                    "open": 4,
                                                    "completed": 6,
                                                    "won_back": 2
                                                },
                                                "created_at": "2026-10-01T09:00:00+00:00",
                                                "updated_at": "2026-10-10T08:00:00+00:00",
                                                "deleted_at": null
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-sequence:view"
                ],
                "x-mcp-tools": [
                    "get_sequence"
                ]
            },
            "patch": {
                "operationId": "v1.sequences.update",
                "description": "```bash\ncurl -X PATCH https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/sequences/9d2f4b6a-1c3e-4f58-8a7b-6e5d4c3b2a19 \\\n  -H \"Authorization: Bearer sbt_...\" \\\n  -H \"Idempotency-Key: 0c4e8a2d-6f1b-4c9e-8d3a-5b7f9e1c2d64\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"active\": false}'\n```\n\nAny subset of the name, the trigger and the switch; fields left out keep their stored values. Switching a sequence off lets every member part-way through go, as `sequence.exited` with the reason `disabled`, and enrols nobody until it runs again; switching it back on enrols nobody retroactively.\n\n`steps`, when present, replaces the whole list in order: a step still at its place keeps its id and a member due it keeps their position, the rest are appended and the extra ones removed from the end. Send `[]` to remove every step. One `sequence.updated` announces the sequence as it then stands.",
                "summary": "Change a sequence",
                "tags": [
                    "Recovery Sequences"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "sequence",
                        "in": "path",
                        "required": true,
                        "description": "The sequence, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateSequenceRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The sequence as it now reads.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SequenceResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-sequence:update"
                ],
                "x-webhook-events": [
                    "sequence.updated",
                    "sequence.exited"
                ],
                "x-mcp-tools": [
                    "update_sequence"
                ]
            },
            "delete": {
                "operationId": "v1.sequences.destroy",
                "description": "Puts the sequence out of use and answers `204`: every member part-way through leaves it as `sequence.exited` with the reason `deleted`, the row and its history stay for the figures, and the id stops answering. There is no undo; build a new sequence instead.",
                "summary": "Delete a sequence",
                "tags": [
                    "Recovery Sequences"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "sequence",
                        "in": "path",
                        "required": true,
                        "description": "The sequence, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-sequence:delete"
                ],
                "x-webhook-events": [
                    "sequence.deleted",
                    "sequence.exited"
                ],
                "x-mcp-tools": [
                    "delete_sequence"
                ]
            }
        },
        "/v1/projects/{project}/sequences/{sequence}/enrollments": {
            "get": {
                "operationId": "v1.sequences.enrollments",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/sequences/9d2f4b6a-1c3e-4f58-8a7b-6e5d4c3b2a19/enrollments?exit_reason=reactivated\" \\\n  -H \"Authorization: Bearer sbt_...\"\n```\n\nEvery passage a member made through the sequence, the newest first: when they entered, the step due next and when, and how the passage ended if it has. `state` is `open`, `completed` or `exited`, and an exited passage says why: `reactivated` (the member paid again, a win), `opted_out` (the platform could not reach them), `disabled` or `deleted`. `exit_reason` keeps one way out; `sort_by` takes `enrolled_at`, `next_due_at`, `completed_at` or `exited_at`.",
                "summary": "List a sequence's enrolments",
                "tags": [
                    "Recovery Sequences"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "sequence",
                        "in": "path",
                        "required": true,
                        "description": "The sequence, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "exit_reason",
                        "in": "query",
                        "description": "Keep only the passages that ended this way: `reactivated` (won back), `opted_out`, `disabled` or `deleted`. Omit for every passage, open ones included.",
                        "schema": {
                            "$ref": "#/components/schemas/SequenceExit"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page of passages, the newest first, each with its member.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/SequenceEnrollmentResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-sequence:view-any"
                ],
                "x-mcp-tools": [
                    "list_sequence_enrollments"
                ]
            }
        },
        "/v1/projects/{project}/referral-program": {
            "get": {
                "operationId": "v1.referral-program.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/referral-program \\\n  -H \"Authorization: Bearer sbt_...\"\n```\n\nThe programme as it stands, with its commission currency's ISO code loaded. `404 RESOURCE_NOT_FOUND` while the project has none.\n\n### Three fields that are easy to misread\n\n> **`plan_ids: []` means every plan, not no plans.** A conversion counts on every plan in the project, including plans added later. Treating it as \"restricted to nothing\" inverts the meaning.\n\n**`commission_period_months`** is `0` for the friend's first payment only, a number of months, or `null` for life. A `fixed` commission is always the first payment only and always reports `0`.\n\n**`commission_value` is a decimal string with four places**: `\"20.0000\"` for 20% of each payment, `\"10.0000\"` for ten of the commission currency. Parse it as a decimal, never a float. `commission_currency_id` is `null` on a percentage, which is earned in each payment's own currency.",
                "summary": "Get the programme",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The programme; 404 `RESOURCE_NOT_FOUND` while the project has none.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ReferralProgramResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "6e2a7a4f-3b8c-4c21-9f6d-2a3b4c5d6e7f",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "active": true,
                                                "customers_only": false,
                                                "approval_required": false,
                                                "reward_kind": "cash",
                                                "reward_days": null,
                                                "commission_type": "percentage",
                                                "commission_value": "20.0000",
                                                "commission_currency_id": null,
                                                "commission_currency": null,
                                                "commission_period_months": 6,
                                                "hold_days": 14,
                                                "minimum_payout": "50.0000",
                                                "friend_reward_kind": "free_days",
                                                "friend_reward_days": 3,
                                                "friend_coupon_id": null,
                                                "payout_details_label": "PayPal email",
                                                "terms": "One referral per household.",
                                                "plan_ids": [],
                                                "created_at": "2026-10-01T09:14:02+00:00",
                                                "updated_at": "2026-10-08T16:41:11+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:view"
                ],
                "x-mcp-tools": [
                    "get_referral",
                    "get_referral_affiliate",
                    "get_referral_program"
                ]
            },
            "put": {
                "operationId": "v1.referral-program.update",
                "description": "```bash\ncurl -X PUT https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/referral-program \\\n  -H \"Authorization: Bearer sbt_...\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"reward_kind\": \"cash\",\n    \"commission_type\": \"percentage\",\n    \"commission_value\": 20,\n    \"commission_period_months\": 6,\n    \"hold_days\": 14,\n    \"friend_reward_kind\": \"free_days\",\n    \"friend_reward_days\": 3,\n    \"payout_details_label\": \"PayPal email\",\n    \"terms\": \"One referral per household.\"\n  }'\n```\n\nThe first PUT creates the programme and answers `201`; every later PUT changes only the fields it carries and answers `200`. Omitting a field keeps its stored value; a first save without `reward_kind` is a free-days programme, and without `friend_reward_kind` gives friends nothing.\n\n> **Changing the terms is not retroactive, and the affiliates are told.** Rewards already in the ledger keep their figures. Every approved or pending affiliate receives the new terms in their chat and by mail when a field they were promised moves: the reward, the commission, the hold, the friend's reward or your own terms text. Who may join, the payout label and the minimum payout are your side and send nothing.",
                "summary": "Set up or change the programme",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateReferralProgramRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The programme as written: 201 when this call created it, 200 after.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: when the creator has neither the Referral Program Addon nor a Growth plan.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when a field is invalid, or the shape does not add up: a free-days reward without days, a cash commission without a type and a rate, a fixed commission without a currency, a percentage above 100, a friend coupon that is not one of the project's codes, or a friend coupon on a project whose plan has no coupon codes.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:update"
                ],
                "x-webhook-events": [
                    "referral.program_updated"
                ],
                "x-mcp-tools": [
                    "update_referral_program"
                ]
            },
            "delete": {
                "operationId": "v1.referral-program.destroy",
                "description": "Removes the programme. Answers `204` with no body.\n\n> **A delete can be refused.** While any affiliate is owed a commission, the delete answers `422` and asks you to record their payouts or switch the programme off instead. Deleting emits no event.",
                "summary": "Delete the programme",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: while the project has no programme.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: while affiliates are still owed commissions.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:delete"
                ],
                "x-mcp-tools": [
                    "delete_referral_program"
                ]
            }
        },
        "/v1/projects/{project}/referral-affiliates": {
            "get": {
                "operationId": "v1.referral-affiliates.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/referral-affiliates?status=approved&per_page=25\" \\\n  -H \"Authorization: Bearer sbt_...\"\n```\n\nPages the programme's affiliates, newest first. `status` is `pending`, `approved` or `suspended`; `member_id` finds the affiliate row of one member. A list row never carries `balances`: read one affiliate for what they are owed.",
                "summary": "List affiliates",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "description": "Keep only affiliates in this standing: `pending` (awaiting the creator's approval), `approved` (their code counts) or `suspended` (their code no longer counts; what they earned stays).",
                        "schema": {
                            "$ref": "#/components/schemas/ReferralAffiliateStatus"
                        }
                    },
                    {
                        "name": "member_id",
                        "in": "query",
                        "description": "Find one member's affiliate row by their member id, as the members endpoints list them.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page, without balances.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/ReferralAffiliateResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:view-any"
                ],
                "x-mcp-tools": [
                    "list_referral_affiliates",
                    "list_referral_payouts",
                    "list_referral_rewards",
                    "list_referrals"
                ]
            },
            "post": {
                "operationId": "v1.referral-affiliates.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/referral-affiliates \\\n  -H \"Authorization: Bearer sbt_...\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"member_id\": \"a1b2c3d4-e5f6-4718-8a9b-0c1d2e3f4a5b\" }'\n```\n\nEnrols a member as an affiliate, approved whatever the programme's switches say, and hands them their code, their links and the programme's terms in their chat and by mail. Emits `referral.affiliate_joined`. Answers `201` with the affiliate.",
                "summary": "Enrol a member by hand",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreReferralAffiliateRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The new affiliate with their balances.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ReferralAffiliateResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: when the creator has neither the Referral Program Addon nor a Growth plan.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when the member is not one of the project's, or already stands in the programme.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:create"
                ],
                "x-webhook-events": [
                    "referral.affiliate_joined"
                ],
                "x-mcp-tools": [
                    "add_referral_affiliate"
                ]
            }
        },
        "/v1/projects/{project}/referral-affiliates/{affiliate}": {
            "get": {
                "operationId": "v1.referral-affiliates.show",
                "description": "One affiliate with their `balances` per currency. An affiliate's own payout details, the wallet address or PayPal email they typed, are never returned by any endpoint: they are the affiliate's money, read only by the dashboard when the creator pays.",
                "summary": "Get an affiliate",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "affiliate",
                        "in": "path",
                        "required": true,
                        "description": "The affiliate, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The affiliate with their balances.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ReferralAffiliateResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "0b1c2d3e-4f50-4617-8a9b-0c1d2e3f4a5b",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "program_id": "6e2a7a4f-3b8c-4c21-9f6d-2a3b4c5d6e7f",
                                                "member_id": "a1b2c3d4-e5f6-4718-8a9b-0c1d2e3f4a5b",
                                                "code": "ADA2026",
                                                "status": "approved",
                                                "days_balance": 0,
                                                "balances": [
                                                    {
                                                        "currency_id": "f0e1d2c3-b4a5-4697-8877-665544332211",
                                                        "pending": "12.0000",
                                                        "earned": "52.0000",
                                                        "payable": "30.0000",
                                                        "paid_out": "10.0000"
                                                    }
                                                ],
                                                "joined_at": "2026-10-02T11:05:00+00:00",
                                                "approved_at": "2026-10-02T11:05:00+00:00",
                                                "created_at": "2026-10-02T11:05:00+00:00",
                                                "updated_at": "2026-10-08T16:41:11+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:view"
                ],
                "x-mcp-tools": [
                    "get_referral",
                    "get_referral_affiliate",
                    "get_referral_program"
                ]
            }
        },
        "/v1/projects/{project}/referrals": {
            "get": {
                "operationId": "v1.referrals.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/referrals?status=converted&since=2026-10-01\" \\\n  -H \"Authorization: Bearer sbt_...\"\n```\n\nPages the friends affiliates brought in, newest first. `status` is `touched`, `converted`, `expired` or `rejected`; `affiliate_id` narrows to one affiliate; `since` keeps the referrals whose friend arrived on or after that instant, so a report can page only what happened after its last run.",
                "summary": "List referrals",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "description": "Keep only referrals in this state: `touched` (the friend arrived, not yet paid), `converted` (their first payment settled), `expired` (the attribution window passed) or `rejected`.",
                        "schema": {
                            "$ref": "#/components/schemas/ReferralStatus"
                        }
                    },
                    {
                        "name": "affiliate_id",
                        "in": "query",
                        "description": "Keep only the referrals one affiliate brought in.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "since",
                        "in": "query",
                        "description": "Keep only referrals whose friend arrived on or after this instant, ISO 8601, so a report can page what happened since its last run.",
                        "schema": {
                            "type": "string",
                            "format": "date-time"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/ReferralResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:view-any"
                ],
                "x-mcp-tools": [
                    "list_referral_affiliates",
                    "list_referral_payouts",
                    "list_referral_rewards",
                    "list_referrals"
                ]
            }
        },
        "/v1/projects/{project}/referrals/{referral}": {
            "get": {
                "operationId": "v1.referrals.show",
                "description": "One referral: how the friend arrived (`source` is `portal_link`, `connector_link` or `code_at_checkout`; `connector` names the bot's platform on a connector link), whether their first payment settled, and `commission_ends_at`, the instant the affiliate stops earning on them on a programme with a period.",
                "summary": "Get a referral",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "referral",
                        "in": "path",
                        "required": true,
                        "description": "The referral, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The referral.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ReferralResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:view"
                ],
                "x-mcp-tools": [
                    "get_referral",
                    "get_referral_affiliate",
                    "get_referral_program"
                ]
            }
        },
        "/v1/projects/{project}/referral-rewards": {
            "get": {
                "operationId": "v1.referral-rewards.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/referral-rewards?affiliate_id=0b1c2d3e-4f50-4617-8a9b-0c1d2e3f4a5b&status=approved\" \\\n  -H \"Authorization: Bearer sbt_...\"\n```\n\nPages the ledger, newest first: one row per settled payment per side of a referral. `affiliate_id`, `status` (`pending`, `approved`, `paid`, `applied`, `reversed`) and `beneficiary` (`referrer`, `friend`) narrow it. A reversal is a row of its own with a negative `amount` and `reverses_reward_id` naming the reward it cancels. The ledger is read-only: rewards are written when a payment settles, made payable by the hold, paid by a recorded payout and reversed by a refund.",
                "summary": "List rewards",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "affiliate_id",
                        "in": "query",
                        "description": "Keep only the rewards one affiliate's referrals earned.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "description": "Keep only rewards in this state: `pending` (inside the hold, or days waiting on the balance), `approved` (payable), `paid` (recorded in a payout), `applied` (days banked on a membership) or `reversed` (taken back by a refund).",
                        "schema": {
                            "$ref": "#/components/schemas/ReferralRewardStatus"
                        }
                    },
                    {
                        "name": "beneficiary",
                        "in": "query",
                        "description": "Keep only the rewards of one side: `referrer` or `friend`.",
                        "schema": {
                            "$ref": "#/components/schemas/ReferralBeneficiary"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/ReferralRewardResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:view-any"
                ],
                "x-mcp-tools": [
                    "list_referral_affiliates",
                    "list_referral_payouts",
                    "list_referral_rewards",
                    "list_referrals"
                ]
            }
        },
        "/v1/projects/{project}/referral-payouts": {
            "get": {
                "operationId": "v1.referral-payouts.index",
                "description": "Pages the payouts the creator recorded, newest first; `affiliate_id` narrows to one affiliate. `rewards_paid` is how many commissions each payout covered.",
                "summary": "List payouts",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "affiliate_id",
                        "in": "query",
                        "description": "Keep only the payouts recorded against one affiliate.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/ReferralPayoutResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:view-any"
                ],
                "x-mcp-tools": [
                    "list_referral_affiliates",
                    "list_referral_payouts",
                    "list_referral_rewards",
                    "list_referrals"
                ]
            },
            "post": {
                "operationId": "v1.referral-payouts.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/referral-payouts \\\n  -H \"Authorization: Bearer sbt_...\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"affiliate_id\": \"0b1c2d3e-4f50-4617-8a9b-0c1d2e3f4a5b\",\n    \"amount\": 30,\n    \"currency_id\": \"f0e1d2c3-b4a5-4697-8877-665544332211\",\n    \"reference\": \"PAYPAL-7F3D1C92\"\n  }'\n```\n\nRecords money that already left: you paid the affiliate outside Subscriby and file it here, so the ledger marks their oldest payable commissions in that currency as paid, first in first out, until the amount is covered. Emits `referral.payout_recorded`. Answers `201` with the payout.\n\n> **The amount is capped at the payable balance.** Read the affiliate's `balances` first; `payable` in the currency is the most a payout may record. Pending commissions are still inside the hold and cannot be paid yet.",
                "summary": "Record a payout",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreReferralPayoutRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The payout.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ReferralPayoutResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when the affiliate is not one of the project's, the currency is unknown, or `amount` exceeds the payable balance in that currency; `error.context.balance` carries what is payable.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:update"
                ],
                "x-webhook-events": [
                    "referral.payout_recorded"
                ],
                "x-mcp-tools": [
                    "record_referral_payout"
                ]
            }
        },
        "/v1/projects/{project}/referral-program/activate": {
            "post": {
                "operationId": "v1.referral-program.activate",
                "description": "Links and codes attribute again and settled payments earn again. Emits `referral.program_updated` with `active` as the one change, and every affiliate is told the terms as they now stand. Answers `200` with the programme.",
                "summary": "Switch the programme on",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The programme after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ReferralProgramResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: when the creator has neither the Referral Program Addon nor a Growth plan.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: while the project has no programme.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:update"
                ],
                "x-webhook-events": [
                    "referral.program_updated"
                ],
                "x-mcp-tools": [
                    "activate_referral_program"
                ]
            }
        },
        "/v1/projects/{project}/referral-program/deactivate": {
            "post": {
                "operationId": "v1.referral-program.deactivate",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/referral-program/deactivate \\\n  -H \"Authorization: Bearer sbt_...\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nThe safe way to stop: links stop attributing and payments stop earning at once, while the ledger and the payouts stay readable and every affiliate is told their link no longer counts new friends. Emits `referral.program_updated`. Answers `200` with the programme.",
                "summary": "Switch the programme off",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The programme after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ReferralProgramResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: when the creator has neither the Referral Program Addon nor a Growth plan.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: while the project has no programme.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:update"
                ],
                "x-webhook-events": [
                    "referral.program_updated"
                ],
                "x-mcp-tools": [
                    "deactivate_referral_program"
                ]
            }
        },
        "/v1/projects/{project}/referral-affiliates/{affiliate}/approve": {
            "post": {
                "operationId": "v1.referral-affiliates.approve",
                "description": "Approves a pending or suspended affiliate: their code counts from now on, and they receive their link, code and the programme's terms in their chat and by mail. Emits `referral.affiliate_approved`. An affiliate already approved is left as they are and nothing is emitted. Answers `200` with the affiliate.",
                "summary": "Approve an affiliate",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "affiliate",
                        "in": "path",
                        "required": true,
                        "description": "The affiliate, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The affiliate after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ReferralAffiliateResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:update"
                ],
                "x-webhook-events": [
                    "referral.affiliate_approved"
                ],
                "x-mcp-tools": [
                    "approve_referral_affiliate"
                ]
            }
        },
        "/v1/projects/{project}/referral-affiliates/{affiliate}/suspend": {
            "post": {
                "operationId": "v1.referral-affiliates.suspend",
                "description": "Their code stops counting new friends and nothing new is earned; what they already earned stays and can still be paid. Emits `referral.affiliate_suspended`. Answers `200` with the affiliate.",
                "summary": "Suspend an affiliate",
                "tags": [
                    "Referral Program"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "affiliate",
                        "in": "path",
                        "required": true,
                        "description": "The affiliate, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The affiliate after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ReferralAffiliateResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-referral:update"
                ],
                "x-webhook-events": [
                    "referral.affiliate_suspended"
                ],
                "x-mcp-tools": [
                    "suspend_referral_affiliate"
                ]
            }
        },
        "/v1/projects/{project}/resources": {
            "get": {
                "operationId": "v1.resources.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/$PROJECT_ID/resources?kind=telegram:channel\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nNewest first, paged with `page` and `per_page`, sortable with `sort_by` (`created_at`, `kind`, `title`, `active`) and `sort_direction`. `kind` narrows to one kind, `connector` to every resource one connector gates.",
                "summary": "List a project's resources",
                "tags": [
                    "Resources"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "kind",
                        "in": "query",
                        "description": "One kind of resource, spelled as the objects spell it: `manual`, or a connector's `connector:kind` as the connector directory lists each connector's `resource_kinds`. Any other shape is refused rather than answered with an empty page.",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "pattern": "^(manual|[a-z][a-z0-9_-]*:[a-z][a-z0-9_-]*)$"
                        }
                    },
                    {
                        "name": "connector",
                        "in": "query",
                        "description": "Every resource one connector gates, by the connector's key as the connector directory lists it.",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "pattern": "^[a-z][a-z0-9_-]*$"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page, newest first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/ResourceResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `kind` is neither `manual` nor `connector:kind`, or `connector` is not a connector key; a typo in an automation is noticed instead of read as \"no resources\".",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-resource:view-any"
                ],
                "x-mcp-tools": [
                    "list_resources"
                ]
            },
            "post": {
                "operationId": "v1.resources.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/resources \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"title\": \"Onboarding PDF\",\n    \"description\": \"https://example.com/onboarding.pdf\"\n  }'\n```\n\nAnswers `201` with the new resource, `kind: \"manual\"`, and emits `project.resource.created`. The payload names no kind: a manual perk is the only resource this endpoint creates, and a place a connector gates is asked for with the link-request endpoint. A resource is what a plan unlocks, and nothing is sold before a connector can deliver it, so a project running no connected connector is refused, a manual perk included: install a connector on the project and connect it first.",
                "summary": "Create a manual perk",
                "tags": [
                    "Resources"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreResourceRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The new resource.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ResourceResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "0d4a7e19-5c2b-4f83-9a61-2e8b7c3d5f10",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "kind": "manual",
                                                "connector": null,
                                                "space": null,
                                                "title": "Onboarding PDF",
                                                "description": "https://example.com/onboarding.pdf",
                                                "active": true,
                                                "created_at": "2026-09-12T10:05:00Z",
                                                "updated_at": "2026-09-12T10:05:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `CONNECTOR_NOT_INSTALLED`: when no connector on the project is connected.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_NOT_INSTALLED": {
                                        "summary": "CONNECTOR_NOT_INSTALLED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_NOT_INSTALLED",
                                                "message": "That connector is not installed on this project.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-not-installed",
                                                "remediation": "Install the connector on the project first (POST /v1/projects/{project}/connectors/{key}), or read GET /v1/projects/{project}/connectors for what is installed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `title` is missing or outside 5 to 255 characters, or `description` exceeds 1,000 characters.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-resource:create"
                ],
                "x-webhook-events": [
                    "project.resource.created"
                ],
                "x-mcp-tools": [
                    "create_resource"
                ]
            }
        },
        "/v1/projects/{project}/resources/{resource}": {
            "get": {
                "operationId": "v1.resources.show",
                "description": "One resource with its place, when it has one.\n\n| Field         | Type           | Notes                                                                                                                                                                                                                       |\n| ------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `kind`        | string         | `manual` for a perk the creator hands over by hand, otherwise `connector:kind` as the [connector directory](https://docs.subscriby.net/api/v1/reference/connectors) lists each connector's `resource_kinds` (`telegram:channel`, `telegram:group`, `telegram:supergroup`). |\n| `connector`   | string or null | The connector key the place is on; `null` for a manual perk.                                                                                                                                                                |\n| `space`       | object or null | The place the resource is bound to: its `id`, the platform's own `external_id` and its `title` as the connector last read it. `null` for a manual perk and for a place-kind resource that was unlinked.                     |\n| `title`       | string         | The resource's name on plan cards; for a linked place, the place's title at link time.                                                                                                                                      |\n| `description` | string or null | Up to 1,000 characters of well-formed HTML, shown as a perk beside the title.                                                                                                                                               |\n| `active`      | boolean        | Whether plans grant it right now. An inactive resource keeps its link and its plans, but new members do not receive it.                                                                                                     |\n\nA manual perk reads `{ \"kind\": \"manual\", \"connector\": null, \"space\": null, … }`.",
                "summary": "Get a resource",
                "tags": [
                    "Resources"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "resource",
                        "in": "path",
                        "required": true,
                        "description": "The resource, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The resource.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ResourceResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "kind": "telegram:channel",
                                                "connector": "telegram",
                                                "space": {
                                                    "id": "3c1f7a58-2b6e-4d90-8f41-6a2e9c5d7b10",
                                                    "external_id": "-1001234567890",
                                                    "title": "Research Premium Lounge"
                                                },
                                                "title": "Research Premium Lounge",
                                                "description": "Daily research notes and the members-only Q&A.",
                                                "active": true,
                                                "created_at": "2026-05-18T10:05:00Z",
                                                "updated_at": "2026-05-18T10:05:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-resource:view"
                ],
                "x-mcp-tools": [
                    "get_resource"
                ]
            },
            "delete": {
                "operationId": "v1.resources.destroy",
                "description": "Deletes the row. Plans that linked it stop granting it. Returns `204 No Content` and emits `project.resource.deleted`.",
                "summary": "Delete a resource",
                "tags": [
                    "Resources"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "resource",
                        "in": "path",
                        "required": true,
                        "description": "The resource, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-resource:delete"
                ],
                "x-webhook-events": [
                    "project.resource.deleted"
                ],
                "x-mcp-tools": [
                    "delete_resource"
                ]
            },
            "patch": {
                "operationId": "v1.resources.update",
                "description": "```bash\ncurl -X PATCH https://api.subscriby.net/v1/projects/$PROJECT_ID/resources/$RESOURCE_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"title\": \"Members lounge (VIP)\" }'\n```\n\nPartial by design: only the fields present in the body change, so a title-only update leaves the description exactly as stored, filtered HTML included, and logs no description edit. `kind` and `space` are not writable here: a resource keeps its kind for life, and its place moves only through the connector.\n\nAnswers `200` with the resource. When at least one field actually changed, `project.resource.updated` fires once with a `changes` map of `{field: {from, to}}`; a body that restates the stored values writes nothing and emits nothing.",
                "summary": "Update a resource",
                "tags": [
                    "Resources"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "resource",
                        "in": "path",
                        "required": true,
                        "description": "The resource, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateResourceRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The resource after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ResourceResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `title` is outside 5 to 255 characters or `description` exceeds 1,000 characters.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-resource:update"
                ],
                "x-webhook-events": [
                    "project.resource.updated"
                ],
                "x-mcp-tools": [
                    "update_resource"
                ]
            }
        },
        "/v1/projects/{project}/resources/link-requests": {
            "post": {
                "operationId": "v1.resources.link-requests.store",
                "description": "A place cannot be created from the API: only the connector can prove it administers the place. This endpoint asks the creator, through the connector, to pick the place; the connector messages them with a picker and the resource appears the moment they choose, announced by `project.resource.linked`. Nothing is created by the call itself.\n\n```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/resources/link-requests \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"kind\": \"telegram:channel\" }'\n```\n\nAnswers `202 Accepted` once the creator has been asked. The dashboard's **Send Request** button on the resource editor and the `request_resource_link` tool run the same action.",
                "summary": "Request a place link",
                "tags": [
                    "Resources"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/RequestResourceLinkRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "202 with `project_id`, `kind` and `status: request_sent`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "project_id": {
                                                    "type": "string",
                                                    "description": "The project the place will belong to.",
                                                    "examples": [
                                                        "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                                    ]
                                                },
                                                "kind": {
                                                    "type": "string",
                                                    "description": "The kind asked for, as sent.",
                                                    "examples": [
                                                        "telegram:channel"
                                                    ]
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "Always `request_sent`: the creator has been asked on the connector.",
                                                    "const": "request_sent",
                                                    "examples": [
                                                        "request_sent"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "project_id",
                                                "kind",
                                                "status"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "kind": "telegram:channel",
                                                "status": "request_sent"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `CONNECTOR_NOT_INSTALLED`: when the project runs no connected connector.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_NOT_INSTALLED": {
                                        "summary": "CONNECTOR_NOT_INSTALLED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_NOT_INSTALLED",
                                                "message": "That connector is not installed on this project.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-not-installed",
                                                "remediation": "Install the connector on the project first (POST /v1/projects/{project}/connectors/{key}), or read GET /v1/projects/{project}/connectors for what is installed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `kind` is `manual` or a bare kind word, when no connected connector on the project gates the kind, or when the creator's linked account cannot be messaged on the connector right now; `error.context.kind` names the kind. `IDENTITY_NOT_LINKED`: when the creator holds no linked account on the connector that has to ask them; they link one under Settings → Security → Linked accounts and the request is retried.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    },
                                    "IDENTITY_NOT_LINKED": {
                                        "summary": "IDENTITY_NOT_LINKED",
                                        "value": {
                                            "error": {
                                                "code": "IDENTITY_NOT_LINKED",
                                                "message": "The creator holds no linked account on the connector that has to ask them.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#identity-not-linked",
                                                "remediation": "Have the creator link their account on the connector from Settings → Security → Linked accounts in the dashboard, then retry; GET /v1/me/identities lists what is linked.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-resource:create"
                ],
                "x-mcp-tools": [
                    "request_resource_link"
                ]
            }
        },
        "/v1/projects/{project}/resources/{resource}/unlink": {
            "post": {
                "operationId": "v1.resources.unlink",
                "description": "Detaches the place from a resource, so `space` reads `null` and the row becomes a placeholder. The resource stays in the project's list and keeps its `kind`, but no longer grants access through the connector. Re-linking goes through the connector again. Answers `200` with the resource and emits `project.resource.unlinked`.",
                "summary": "Unlink a resource's place",
                "tags": [
                    "Resources"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "resource",
                        "in": "path",
                        "required": true,
                        "description": "The resource, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The resource after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ResourceResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-resource:update"
                ],
                "x-webhook-events": [
                    "project.resource.unlinked"
                ],
                "x-mcp-tools": [
                    "unlink_resource"
                ]
            }
        },
        "/v1/projects/{project}/resources/{resource}/activate": {
            "post": {
                "operationId": "v1.resources.activate",
                "description": "The switch on the dashboard's resource row, on. A plan grants only its active resources, so the resource returns to what new members receive. Idempotent and answers `200` with the resource; only a flip emits `project.resource.updated`, with `changes.active`.",
                "summary": "Activate a resource",
                "tags": [
                    "Resources"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "resource",
                        "in": "path",
                        "required": true,
                        "description": "The resource, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The resource after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ResourceResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-resource:update"
                ],
                "x-webhook-events": [
                    "project.resource.updated"
                ],
                "x-mcp-tools": [
                    "activate_resource"
                ]
            }
        },
        "/v1/projects/{project}/resources/{resource}/deactivate": {
            "post": {
                "operationId": "v1.resources.deactivate",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/resources/$RESOURCE_ID/deactivate \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nThe switch on the dashboard's resource row, off. An inactive resource stays in the project and keeps its place, but a plan grants only its active resources, so it drops out of what new members receive until it is switched back on. Idempotent and answers `200` with the resource; only a flip emits `project.resource.updated`, with `changes.active`.",
                "summary": "Deactivate a resource",
                "tags": [
                    "Resources"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "resource",
                        "in": "path",
                        "required": true,
                        "description": "The resource, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The resource after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/ResourceResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-resource:update"
                ],
                "x-webhook-events": [
                    "project.resource.updated"
                ],
                "x-mcp-tools": [
                    "deactivate_resource"
                ]
            }
        },
        "/v1/projects/{project}/retention": {
            "get": {
                "operationId": "v1.retention.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/retention \\\n  -H \"Authorization: Bearer sbt_...\"\n```\n\nThe grace window with the ladder it implies in words, the digest switch, the cancellation question, the three offers with the coupons they carry, and the two nurture windows: `checkout_stall_hours` (how long a checkout may stay open with no settled charge before the hourly sweep counts it as stalled and the stalled-checkout sequences start; 1 to 24, 1 by default) and `trial_notice_days` (how many days before a trial without a card ends its trial-ending sequences start; 1 to 14, 3 by default; a shorter trial enrols at its start). The row is created with the defaults on the first read, so a project never answers `404` here.\n\n### Two fields that are easy to misread\n\n**`offers_available` is the owner's plan, not a setting.** It is `true` on Growth and with the Revenue Recovery Addon. The three offer fields are stored whatever it says; the cancellation screen reads them only while it is `true`.\n\n**`ladder` is derived from `grace_days`.** It is the sentence the dashboard and the bot show for the window, in the token holder's language; write `grace_days` and read `ladder` back.",
                "summary": "Read the settings",
                "tags": [
                    "Revenue Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The settings with the ladder in words and whether the offers are available.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RetentionSettingsResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "grace_days": 7,
                                                "ladder": "A failed renewal keeps access for 7 days: a notice at the failure, a reminder on day 3, a final warning on the last day, then access pauses until a charge settles.",
                                                "digest_enabled": true,
                                                "cancel_feedback_enabled": true,
                                                "checkout_stall_hours": 1,
                                                "trial_notice_days": 3,
                                                "offers_available": true,
                                                "offer_pause_enabled": true,
                                                "offer_discount_coupon": {
                                                    "id": "3b7c9d1e-5f24-4a86-9c0b-2d4e6f8a1b3c",
                                                    "code": "STAY20"
                                                },
                                                "offer_return_coupon": null,
                                                "updated_at": "2026-10-12T09:00:00+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-mcp-tools": [
                    "get_retention_settings"
                ]
            },
            "put": {
                "operationId": "v1.retention.update",
                "description": "```bash\ncurl -X PUT https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/retention \\\n  -H \"Authorization: Bearer sbt_...\" \\\n  -H \"Idempotency-Key: 6b1f0d2e-9c3a-4e8b-b2d1-7a9c5e3f1d04\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"grace_days\": 10, \"offer_pause_enabled\": true, \"offer_return_coupon_id\": \"3b7c9d1e-5f24-4a86-9c0b-2d4e6f8a1b3c\"}'\n```\n\nEvery field is optional and the row keeps its stored value for each one left out, so a client can flip the digest without restating the window. A coupon must be one of the project's own; send `null` to clear an offer. The two nurture windows are whole numbers within their bounds (`checkout_stall_hours` 1 to 24, `trial_notice_days` 1 to 14); a checkout already open is judged by the window in force when the hourly sweep runs. The answer is the settings as they now read.\n\n> A grace window of `0` pauses access at the first failure. The never-paid trial keeps today's immediate revoke whatever the window says, and a one-time purchase never enters grace.",
                "summary": "Change the settings",
                "tags": [
                    "Revenue Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateRetentionSettingsRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The settings as they now read.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RetentionSettingsResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:update"
                ],
                "x-mcp-tools": [
                    "update_retention_settings"
                ]
            }
        },
        "/v1/projects/{project}/retention/stats": {
            "get": {
                "operationId": "v1.retention.stats",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/retention/stats?period=30d\" \\\n  -H \"Authorization: Bearer sbt_...\"\n```\n\nWhat the programme did over the window, as the dashboard card reads it: the failed renewals, the reminders sent, the pauses, the recoveries with what they brought back restated in US dollars, the restorations, the win-back steps sent and the members won back (the churn trigger alone), the cancellation screens with the offers shown and taken, and why members cancelled with each reason's share; then the nurture block: the leads who arrived, entered a lead sequence and bought while it ran, the checkouts started, stalled and recovered with what the recovered ones were worth in US dollars, and the trials without a card a sequence took and the ones whose member paid while it ran. The two \"right now\" figures, the members in grace and the members paused, ignore the window.",
                "summary": "Read the figures",
                "tags": [
                    "Revenue Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "period",
                        "in": "query",
                        "description": "The window the figures cover: `7d`, `14d`, `30d` (the default), `60d`, `90d`, `1y`, `mtd`, `qtd`, `ytd` or `all`. The two \"right now\" figures ignore it.",
                        "schema": {
                            "$ref": "#/components/schemas/DashboardPeriod"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The figures the dashboard card reads, with the reasons members gave.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RetentionStatsResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view-any"
                ],
                "x-mcp-tools": [
                    "get_retention_stats"
                ]
            }
        },
        "/v1/projects/{project}/retention/cancellations": {
            "get": {
                "operationId": "v1.retention.cancellations",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/retention/cancellations?reason=too_expensive&per_page=25\" \\\n  -H \"Authorization: Bearer sbt_...\"\n```\n\nEvery cancellation screen a member reached, newest first: the member, the plan, the reason they picked, their own words, the offer shown and whether they took it, where they answered, and the pause's dates where they took one. `reason` and `surface` narrow the page; `sort_by` takes `created_at`, `reason`, `surface` or `offer_taken`.",
                "summary": "List the cancellation screens",
                "tags": [
                    "Revenue Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "reason",
                        "in": "query",
                        "description": "Keep only the records whose member gave this reason: `too_expensive`, `not_using_enough`, `not_enough_content`, `content_not_expected`, `found_another_community`, `not_the_right_fit`, `taking_a_break`, `got_what_i_needed`, `technical_problems`, `signed_up_by_mistake` or `other`.",
                        "schema": {
                            "$ref": "#/components/schemas/CancellationReason"
                        }
                    },
                    {
                        "name": "surface",
                        "in": "query",
                        "description": "Keep only the records made on the `portal` or in a connector chat (`bot`).",
                        "schema": {
                            "$ref": "#/components/schemas/CancellationSurface"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page of cancellation screens, newest first, each with its member and plan.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/CancellationRecordResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view-any"
                ],
                "x-mcp-tools": [
                    "list_cancellation_feedback"
                ]
            }
        },
        "/v1/projects/{project}/retention/activity": {
            "get": {
                "operationId": "v1.retention.activity",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/retention/activity?kind=payment_recovered\" \\\n  -H \"Authorization: Bearer sbt_...\"\n```\n\nThe ledger behind every figure: one row per notice, offer, feedback and win-back message, with the member, the kind, the channel that carried it, when it went out, and, once a charge settled after it, `converted_at` and the payment that counted it. `kind` keeps one kind of row; `sort_by` takes `created_at`, `sent_at` or `kind`.\n\n> A row converts when the next charge settles for that member, which is how the figures count a recovery and a member won back; a notice that converts is not a notice that worked on its own, only one that preceded the payment.",
                "summary": "List the activity ledger",
                "tags": [
                    "Revenue Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "kind",
                        "in": "query",
                        "description": "Keep only one kind of row: `payment_failed_notice`, `grace_reminder`, `grace_final_warning`, `access_suspended`, `access_restored`, `payment_recovered`, `offer_shown`, `offer_taken`, `feedback` or `sequence_step`.",
                        "schema": {
                            "$ref": "#/components/schemas/RetentionTouchKind"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page of ledger rows, newest first, each with its member, coupon and step.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/RetentionTouchResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view-any"
                ],
                "x-mcp-tools": [
                    "list_retention_activity"
                ]
            }
        },
        "/v1/projects/{project}/retention/checkouts": {
            "get": {
                "operationId": "v1.retention.checkouts",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/retention/checkouts?stalled=true&recovered=false\" \\\n  -H \"Authorization: Bearer sbt_...\"\n```\n\nEvery checkout a member started, newest first: the member, the plan they were buying, the rail and where they started (`portal` or `bot`), the order reference the rail was given, when it started, when the hourly sweep counted it as stalled, when a charge finished it or another checkout superseded it, summed up as `outcome`: `open` while nothing has settled and the sweep has not counted it, `stalled` once the project's checkout window passed with no settled charge, `recovered` when a charge settled after that, `completed` when a charge settled before it could stall, and `superseded` when it closed with no charge of its own because the member paid through another checkout or already held a live membership when the sweep looked. One charge finishes one checkout and brings back one stalled checkout, so a member who tapped Pay three times and paid once has one `completed` and two `superseded`. `enrollment_id` names the stalled-checkout sequence passage the stall opened. `stalled` and `recovered` (booleans; `recovered` reads among the stalled rows, and a stalled row another checkout superseded answers neither), `plan_id` and `member_id` narrow the page; `sort_by` takes `started_at`, `stalled_at` or `completed_at`.\n\n> An access code redemption or a free trial start is not a checkout and never appears here. A member is counted as stalled at most once a day however many checkouts they started; the older open ones are stamped stalled without a second `checkout.stalled` or a second passage.",
                "summary": "List the checkouts",
                "tags": [
                    "Revenue Recovery"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "stalled",
                        "in": "query",
                        "description": "Keep only the checkouts the hourly sweep counted as stalled (`true`), or only the ones it never did (`false`). Omit for both.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "true",
                                "false",
                                "1",
                                "0"
                            ]
                        }
                    },
                    {
                        "name": "recovered",
                        "in": "query",
                        "description": "Keep only the stalled checkouts a charge finished after all (`true`), or only the stalled ones still open (`false`). Omit for both.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "true",
                                "false",
                                "1",
                                "0"
                            ]
                        }
                    },
                    {
                        "name": "plan_id",
                        "in": "query",
                        "description": "Keep only the checkouts of one plan.",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "member_id",
                        "in": "query",
                        "description": "Keep only one member's checkouts, by their member id as the members endpoints list them.",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page of checkouts, newest first, each with its member and plan.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/CheckoutAttemptResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view-any"
                ],
                "x-mcp-tools": [
                    "list_checkouts"
                ]
            }
        },
        "/v1/roles": {
            "get": {
                "operationId": "v1.roles.index",
                "description": "```bash\ncurl https://api.subscriby.net/v1/roles \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nEvery role across the teams the caller can see, with its permission codes. Visibility is the union of every team the caller owns or belongs to; a role from a team the caller cannot see answers `404 RESOURCE_NOT_FOUND` rather than `403`, so existence never leaks.",
                "summary": "List roles",
                "tags": [
                    "Roles"
                ],
                "parameters": [
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Roles across every team the caller belongs to.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/RoleResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "role:view-any"
                ],
                "x-mcp-tools": [
                    "list_roles"
                ]
            },
            "post": {
                "operationId": "v1.roles.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/roles \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n        \"team_id\": \"a83f0d51-4c92-4b7e-8615-2fd9e70a3c86\",\n        \"code\": \"support-agent\",\n        \"name\": \"Support Agent\",\n        \"description\": \"Answers tickets, cannot touch billing\",\n        \"permissions\": [\"support-conversation:view-any\", \"support-conversation:update\"]\n      }'\n```\n\n> **Choose the code deliberately.** `code` is the stable identifier permissions are addressed by. It must be unique within the team and **cannot be changed afterwards**: renaming one would detach every assignment that referenced it. Only `name`, `description` and the permission set are mutable.\n\n`permissions` accepts codes from the permission catalog in `entity:action` form. An unknown code is refused rather than silently dropped, so a typo fails loudly instead of creating a role that grants less than you think. Omit the field for a role that grants nothing yet.\n\nAnswers `201` with the role and emits `role.created`.",
                "summary": "Create a role",
                "tags": [
                    "Roles"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreRoleRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The role resource as a 201.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RoleResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: below the Growth tier; nothing changes.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: when `team_id` is not one of the caller's teams.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when a role with that code already exists in the team (`error.context.code` names it), or a permission code is unknown.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "role:create"
                ],
                "x-webhook-events": [
                    "role.created"
                ],
                "x-mcp-tools": [
                    "create_role"
                ]
            }
        },
        "/v1/roles/{role}": {
            "get": {
                "operationId": "v1.roles.show",
                "description": "One role with its permission codes. `permissions` is a flat array of the exact ability strings granted by this role, the same strings used as token abilities, so you can match roles against tokens without a second round-trip.",
                "summary": "Get a role",
                "tags": [
                    "Roles"
                ],
                "parameters": [
                    {
                        "name": "role",
                        "in": "path",
                        "required": true,
                        "description": "The role, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The role resource with its permissions.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RoleResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "d05e1a83-7c46-4f29-b613-8ae407c9d251",
                                                "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                                "code": "manager",
                                                "name": "Manager",
                                                "description": "Manage plans, resources, and subscribers",
                                                "owner_user_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "permissions": [
                                                    "project:view",
                                                    "project:update",
                                                    "project-user:view-any",
                                                    "project-user:update"
                                                ],
                                                "created_at": "2026-05-18T10:05:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "role:view"
                ],
                "x-mcp-tools": [
                    "get_role"
                ]
            },
            "patch": {
                "operationId": "v1.roles.update",
                "description": "```bash\ncurl -X PATCH https://api.subscriby.net/v1/roles/$ROLE_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\": \"Senior Support Agent\", \"permissions\": [\"support-conversation:view-any\"]}'\n```\n\n> **Permissions replace, they do not merge.** Sending `permissions` sets the role's permissions to exactly that list; anything omitted is revoked. **Omit the key entirely** to leave the existing set untouched while changing only the name or description.\n\nAnswers `200` with the role and emits `role.updated`.",
                "summary": "Update a role",
                "tags": [
                    "Roles"
                ],
                "parameters": [
                    {
                        "name": "role",
                        "in": "path",
                        "required": true,
                        "description": "The role, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreRoleRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The updated role resource.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/RoleResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: below the Growth tier; nothing changes.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `code` or `team_id` is sent (a role cannot be renamed at the code level or moved between teams), or a permission code is unknown.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "role:update"
                ],
                "x-webhook-events": [
                    "role.updated"
                ],
                "x-mcp-tools": [
                    "update_role"
                ]
            },
            "delete": {
                "operationId": "v1.roles.destroy",
                "description": "```bash\ncurl -X DELETE https://api.subscriby.net/v1/roles/$ROLE_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nReturns `204 No Content`, and detaches the role's permissions on the way out. Anyone currently holding the role loses whatever it granted them; they stay in the team. Not gated by tier. Emits `role.deleted`.\n\nRestricted to whoever **created** the role, unless the caller **owns** the team. Belonging to a team is not licence to dismantle how everyone else in it is permissioned.",
                "summary": "Delete a role",
                "tags": [
                    "Roles"
                ],
                "parameters": [
                    {
                        "name": "role",
                        "in": "path",
                        "required": true,
                        "description": "The role, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the caller neither created the role nor owns the team; `error.context.role_id` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "role:delete"
                ],
                "x-webhook-events": [
                    "role.deleted"
                ],
                "x-mcp-tools": [
                    "delete_role"
                ]
            }
        },
        "/v1/projects/{project}/links": {
            "get": {
                "operationId": "v1.links.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/links?archived=false&per_page=25&page=1\" \\\n  -H \"Authorization: Bearer sbt_...\"\n```\n\nPages the project's links, newest first, live and archived alike unless `archived` says otherwise; `search` finds links whose name or slug contains the text. Every row carries the three addresses in `urls`.\n\n> `archived=false` keeps expired links too: they are still the creator's and still carry their figures. Read `state` on each row, which is `live`, `expired` or `archived`.",
                "summary": "List a project's links",
                "tags": [
                    "Smart Links"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "archived",
                        "in": "query",
                        "description": "Keep only archived links (`true`) or only links still in use (`false`), expired ones included. Omit for every link.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "true",
                                "false",
                                "1",
                                "0"
                            ]
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "description": "Find links whose name or slug contains this text, case-insensitively.",
                        "schema": {
                            "type": "string",
                            "maxLength": 120
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page of links, newest first, each with its three addresses.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/SmartLinkResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-link:view-any"
                ],
                "x-mcp-tools": [
                    "list_links"
                ]
            },
            "post": {
                "operationId": "v1.links.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/links \\\n  -H \"Authorization: Bearer sbt_...\" \\\n  -H \"Idempotency-Key: 6b1f0d2e-9c3a-4e8b-b2d1-7a9c5e3f1d04\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\":\"YouTube description\",\"slug\":\"youtube\",\"destination\":\"plan\",\"plan_id\":\"0c9d8e7f-6a5b-4c3d-8e2f-1a2b3c4d5e6f\"}'\n```\n\nAnswers `201` with the new link, its code minted and its three addresses built. `destination` is `portal` (the portal home), `plan` (the checkout of one plan, which needs `plan_id`) or `bot` (the project's bot; the portal home when no bot is connected). `expires_at`, in the future, stops the link counting after that moment.\n\nThe slug is lowercased before it is stored and checked, so `Promo` when `promo` exists is `422 VALIDATION_FAILED`, not a second link; `go`, `embed`, `portal`, `bot`, `direct`, `new` and `edit` are reserved. Emits `link.created`.",
                "summary": "Create a link",
                "tags": [
                    "Smart Links"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreSmartLinkRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The new link, `201`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SmartLinkResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-link:create"
                ],
                "x-webhook-events": [
                    "link.created"
                ],
                "x-mcp-tools": [
                    "create_link"
                ]
            }
        },
        "/v1/projects/{project}/links/funnel": {
            "get": {
                "operationId": "v1.links.funnel",
                "description": "```bash\ncurl https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/links/funnel \\\n  -H \"Authorization: Bearer sbt_...\"\n```\n\nEvery link, live and archived, each with its lifetime `clicks`, `leads` (the members it brought), `checkouts` (those who started a purchase, in any state), `paid` (those who made a successful payment), `conversion_rate` (paid per hundred clicks) and `revenue` (everything those members ever paid, per currency and restated in US dollars); the `direct` row for the members no link brought; and `totals`, which equal the project's own figures, so the rows add up.\n\n> The figures are lifetime by design and count removed members and ended purchases, so two channels compare on everything each ever brought. The dashboard's date window never narrows them.",
                "summary": "The project's funnel",
                "tags": [
                    "Smart Links"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "`links`, `direct` and `totals`; the totals are the project's own figures, so the rows add up.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "links": {
                                                    "type": "array",
                                                    "description": "One funnel row per Smart Link of the project, live and archived alike, newest first.",
                                                    "items": {
                                                        "type": "array",
                                                        "items": {}
                                                    }
                                                },
                                                "direct": {
                                                    "type": "array",
                                                    "description": "The Direct row: the members no link brought, counted the same way, with `link_id` and `slug` null.",
                                                    "items": {}
                                                },
                                                "totals": {
                                                    "type": "object",
                                                    "description": "The sum of every row above, which equals the project's own figures.",
                                                    "properties": {
                                                        "clicks": {
                                                            "type": "integer",
                                                            "description": "Every link's lifetime clicks added up; the Direct row has none.",
                                                            "examples": [
                                                                42
                                                            ]
                                                        },
                                                        "leads": {
                                                            "type": "integer",
                                                            "description": "Every member of the project, credited to a link or Direct.",
                                                            "examples": [
                                                                129
                                                            ]
                                                        },
                                                        "checkouts": {
                                                            "type": "integer",
                                                            "description": "Those members who started at least one purchase.",
                                                            "examples": [
                                                                65
                                                            ]
                                                        },
                                                        "paid": {
                                                            "type": "integer",
                                                            "description": "Those members who made at least one successful payment.",
                                                            "examples": [
                                                                58
                                                            ]
                                                        },
                                                        "revenue_usd": {
                                                            "type": "string",
                                                            "description": "Everything they ever paid, restated in US dollars, a decimal string with two places.",
                                                            "examples": [
                                                                "696.00"
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "clicks",
                                                        "leads",
                                                        "checkouts",
                                                        "paid",
                                                        "revenue_usd"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "links",
                                                "direct",
                                                "totals"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "links": [
                                                    {
                                                        "link_id": "1e2a4c6b-3d5f-4a7b-9c1d-2e3f4a5b6c7d",
                                                        "name": "YouTube description",
                                                        "slug": "youtube",
                                                        "archived": false,
                                                        "clicks": 42,
                                                        "leads": 9,
                                                        "checkouts": 4,
                                                        "paid": 3,
                                                        "conversion_rate": 7.14,
                                                        "revenue": {
                                                            "usd": "36.00",
                                                            "by_currency": [
                                                                {
                                                                    "currency_id": "…",
                                                                    "currency": "USD",
                                                                    "amount": "36.00"
                                                                }
                                                            ]
                                                        }
                                                    }
                                                ],
                                                "direct": {
                                                    "link_id": null,
                                                    "name": "Direct",
                                                    "slug": null,
                                                    "archived": false,
                                                    "clicks": 0,
                                                    "leads": 120,
                                                    "checkouts": 61,
                                                    "paid": 55,
                                                    "conversion_rate": 0,
                                                    "revenue": {
                                                        "usd": "660.00",
                                                        "by_currency": [
                                                            {
                                                                "currency_id": "…",
                                                                "currency": "USD",
                                                                "amount": "660.00"
                                                            }
                                                        ]
                                                    }
                                                },
                                                "totals": {
                                                    "clicks": 42,
                                                    "leads": 129,
                                                    "checkouts": 65,
                                                    "paid": 58,
                                                    "revenue_usd": "696.00"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-link:view-any"
                ],
                "x-mcp-tools": [
                    "get_link_funnel"
                ]
            }
        },
        "/v1/projects/{project}/links/{smartLink}": {
            "get": {
                "operationId": "v1.links.show",
                "description": "One link with its plan's name loaded. A link of another project is `404 RESOURCE_NOT_FOUND`.\n\n### Three fields that are easy to misread\n\n**`urls.bot` is null without a bot.** The deep link exists only while the project runs a bot that hands out start links; the web address and the embed page are always there.\n\n**`code` never changes, `slug` may.** Share `urls.web` where the slug is fine to change later; print `urls.bot` or a QR of `urls.web` and rely on the code, which survives every rename because the slug's redirect runs through the portal, where the code takes over.\n\n**`clicks.total` is one per visitor address per hour.** A creator reading their own page a dozen times adds one, and no analytics cookie is set on a stranger.",
                "summary": "Get a link",
                "tags": [
                    "Smart Links"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "smartLink",
                        "in": "path",
                        "required": true,
                        "description": "The link, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The link with its three addresses.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SmartLinkResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "1e2a4c6b-3d5f-4a7b-9c1d-2e3f4a5b6c7d",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "name": "YouTube description",
                                                "slug": "youtube",
                                                "code": "TUBE234",
                                                "destination": {
                                                    "type": "plan",
                                                    "plan_id": "0c9d8e7f-6a5b-4c3d-8e2f-1a2b3c4d5e6f",
                                                    "plan_name": "Premium"
                                                },
                                                "urls": {
                                                    "web": "https://my.subscriby.net/research-premium/go/youtube",
                                                    "bot": "https://t.me/ResearchPremiumBot?start=via_TUBE234",
                                                    "embed": "https://my.subscriby.net/research-premium/embed/plans?via=TUBE234"
                                                },
                                                "state": "live",
                                                "expires_at": null,
                                                "archived_at": null,
                                                "clicks": {
                                                    "total": 42,
                                                    "last_at": "2026-10-10T08:00:00+00:00"
                                                },
                                                "created_at": "2026-10-01T09:00:00+00:00",
                                                "updated_at": "2026-10-10T08:00:00+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-link:view"
                ],
                "x-mcp-tools": [
                    "get_link"
                ]
            },
            "patch": {
                "operationId": "v1.links.update",
                "description": "Any subset of the create shape; omitted fields keep their stored value. Renaming `slug` moves the web address and nothing else. `expires_at: null` clears an expiry. A `plan_id` is dropped when the destination stops being a plan. Emits `link.updated` with the fields that moved.",
                "summary": "Change a link",
                "tags": [
                    "Smart Links"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "smartLink",
                        "in": "path",
                        "required": true,
                        "description": "The link, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateSmartLinkRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The link as it now reads.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SmartLinkResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-link:update"
                ],
                "x-webhook-events": [
                    "link.updated"
                ],
                "x-mcp-tools": [
                    "update_link"
                ]
            },
            "delete": {
                "operationId": "v1.links.destroy",
                "description": "Answers `204`. The address keeps landing on the portal home, so a flyer or a bio that carries it never shows anyone an error; the figures stay on the funnel; the link cannot be put back in use. Emits `link.archived` the first time; a second `DELETE` changes nothing and answers `204` again.",
                "summary": "Archive a link",
                "tags": [
                    "Smart Links"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "smartLink",
                        "in": "path",
                        "required": true,
                        "description": "The link, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-link:delete"
                ],
                "x-webhook-events": [
                    "link.archived"
                ],
                "x-mcp-tools": [
                    "archive_link"
                ]
            }
        },
        "/v1/projects/{project}/links/{smartLink}/funnel": {
            "get": {
                "operationId": "v1.links.link-funnel",
                "description": "The same row for one link, under `data`.",
                "summary": "One link's funnel",
                "tags": [
                    "Smart Links"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "smartLink",
                        "in": "path",
                        "required": true,
                        "description": "The link, resolved within the project by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The link's own funnel row.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SmartLinkFunnelResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-link:view"
                ],
                "x-mcp-tools": [
                    "get_link_funnel"
                ]
            }
        },
        "/v1/subscriptions": {
            "get": {
                "operationId": "v1.subscriptions.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/subscriptions?status=active\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe held subscriptions across every project the token reaches, newest first, paged with `page` and `per_page` (default 25; `limit` is accepted as an alias). `status` matches a single payment status and `plan_id` scopes to one plan. Rows carry no `grants`.\n\nA token minted with `scope:project:<uuid>` entries lists only the subscriptions of those projects, and a subscription of any other project is `404 RESOURCE_NOT_FOUND` on every endpoint of this resource.",
                "summary": "List subscriptions",
                "tags": [
                    "Subscriptions"
                ],
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "description": "Match a single payment status: `trialing`, `active`, `incomplete`, `expired`, `past_due`, `canceled`, `unpaid`, `paused`, `processing`, `succeeded`, `capturable` or `failed`. An unknown value is refused.",
                        "schema": {
                            "anyOf": [
                                {
                                    "$ref": "#/components/schemas/SubscriptionStatus"
                                },
                                {
                                    "type": "null"
                                }
                            ]
                        }
                    },
                    {
                        "name": "plan_id",
                        "in": "query",
                        "description": "Scope to one plan.",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page of held subscriptions, newest first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/SubscriptionResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `status` is not a payment status or `plan_id` is not a UUID.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view-any"
                ],
                "x-mcp-tools": [
                    "list_subscriptions"
                ]
            }
        },
        "/v1/subscriptions/{subscription}": {
            "get": {
                "operationId": "v1.subscriptions.show",
                "description": "One subscription with its `grants` embedded.\n\n`payment_status` is one of `trialing`, `active`, `incomplete`, `expired`, `past_due`, `canceled`, `unpaid`, `paused`, `processing`, `succeeded`, `capturable` or `failed` (the `subscriby://enums/subscription-status` MCP resource lists them).\n\n`compensation_seconds` is the outage time [Outage Compensation](https://docs.subscriby.net/disaster-recovery/connector-outages#outage-compensation) has banked on the purchase, `0` for almost every subscription. `ends_at` already includes it: a one-time purchase simply ends later, while a recurring plan's `ends_at` runs that many seconds past the period the member last paid for, so the renewal the gateway bills is `ends_at` minus `compensation_seconds`.",
                "summary": "Get a subscription",
                "tags": [
                    "Subscriptions"
                ],
                "parameters": [
                    {
                        "name": "subscription",
                        "in": "path",
                        "required": true,
                        "description": "The subscription, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The subscription, its access grants embedded.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/SubscriptionResource"
                                                },
                                                {
                                                    "type": "object",
                                                    "required": [
                                                        "grants"
                                                    ]
                                                }
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "method_id": "8b0c4a15-e792-4360-95d8-1f47c0b3e926",
                                                "payment_status": "active",
                                                "payment_price": "29.00",
                                                "currency_id": "8f27a0d4-63be-4915-8c07-1a5d9e34b628",
                                                "trial_ends_at": null,
                                                "ends_at": "2026-06-18T10:05:00Z",
                                                "canceled": false,
                                                "compensation_seconds": 0,
                                                "redeemed_at": null,
                                                "created_at": "2026-05-18T10:05:00Z",
                                                "updated_at": "2026-05-18T10:05:00Z",
                                                "grants": [
                                                    {
                                                        "id": "7d1c3e9a-2b64-4f0e-9a58-3c6b1d8e2f47",
                                                        "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                        "resource_id": "c9e21f37-8a4b-4d56-b1e0-2f7c9d3a6e15",
                                                        "window_id": null,
                                                        "identity_id": "0c2d8a7e-4b1f-4d3e-9a6b-2f5e8c1d7a90",
                                                        "connector": "telegram",
                                                        "mode": "bearer_link",
                                                        "state": "granted",
                                                        "reference": "https://t.me/+AbCdEfGhIjKlMnOp",
                                                        "granted_at": "2026-09-12T10:05:00Z",
                                                        "revoked_at": null,
                                                        "failure_kind": null,
                                                        "failure_detail": null,
                                                        "created_at": "2026-09-12T10:04:58Z"
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-mcp-tools": [
                    "get_subscription"
                ]
            }
        },
        "/v1/subscriptions/{subscription}/grants": {
            "get": {
                "operationId": "v1.subscriptions.grants.index",
                "description": "```bash\ncurl https://api.subscriby.net/v1/subscriptions/$SUBSCRIPTION_ID/grants \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nEvery grant the purchase holds, one per resource and dated window, oldest first. Never paginated.\n\nA **grant** is the access ledger's record that a purchase admits its holder to one resource: one row per resource, and per dated window for a pass. It says which connector gave the access, how (`mode`), where it stands (`state`) and, when it failed, why. Read it to know whether a member is actually in the channel rather than inferring it from the payment status.\n\n- `mode` is `bearer_link` (a personal invite link the member comes through), `membership` (the connector added the member itself), `role` (a role was assigned) or `creator_task` (the creator has to do something by hand).\n- `state` is `pending_identity` (the member has not linked an account on that connector yet; `member.resource_pending` was raised, and the grant is issued the moment they connect one), `pending` (issued, not yet used), `held` (issued ahead of a pass window and released when it opens), `granted`, `revoked` or `failed`.\n- `identity_id` is the connector account admitted, the same id the [member's identities endpoint](https://docs.subscriby.net/api/v1/reference/members) returns, or `null` while none is linked or for a hand-arranged perk.\n- `reference` is the connector's handle on the grant (the invite link on a connector that grants by link), `null` before anything was issued. Treat it as a secret: whoever holds a bearer link can use it.\n- A `failed` grant carries `failure_kind` (`unreachable`, `not_permitted`, `target_missing`, `rate_limited`, `configuration`, `transient`, `other`) and `failure_detail`, the sentence the creator sees in the dashboard.\n\nThe ledger is written by the same job that mints invite links, so a purchase's grants appear moments after `member.resource_added` fires; a revoked link stays as a `revoked` row rather than disappearing, so history is never lost.",
                "summary": "List a subscription's grants",
                "tags": [
                    "Subscriptions"
                ],
                "parameters": [
                    {
                        "name": "subscription",
                        "in": "path",
                        "required": true,
                        "description": "The subscription, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Array of `AccessGrantResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "$ref": "#/components/schemas/AccessGrantResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "7d1c3e9a-2b64-4f0e-9a58-3c6b1d8e2f47",
                                                    "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                    "resource_id": "c9e21f37-8a4b-4d56-b1e0-2f7c9d3a6e15",
                                                    "window_id": null,
                                                    "identity_id": "0c2d8a7e-4b1f-4d3e-9a6b-2f5e8c1d7a90",
                                                    "connector": "telegram",
                                                    "mode": "bearer_link",
                                                    "state": "granted",
                                                    "reference": "https://t.me/+AbCdEfGhIjKlMnOp",
                                                    "granted_at": "2026-09-12T10:05:00Z",
                                                    "revoked_at": null,
                                                    "failure_kind": null,
                                                    "failure_detail": null,
                                                    "created_at": "2026-09-12T10:04:58Z"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-mcp-tools": [
                    "list_subscription_grants"
                ]
            }
        },
        "/v1/subscriptions/{subscription}/cancel": {
            "post": {
                "operationId": "v1.subscriptions.cancel",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/subscriptions/$SUBSCRIPTION_ID/cancel \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nCancel is asynchronous: the endpoint answers `202 Accepted` once cancellation is queued. Provider-side cancellation (Stripe, PayPal, Razorpay, Paystack and the others) and the accompanying `subscription.cancelled` event happen on the background worker.",
                "summary": "Cancel a subscription",
                "tags": [
                    "Subscriptions"
                ],
                "parameters": [
                    {
                        "name": "subscription",
                        "in": "path",
                        "required": true,
                        "description": "The subscription, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "202": {
                        "description": "202 with `cancellation_queued`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "subscription_id": {
                                                    "type": "string",
                                                    "description": "The purchase being cancelled.",
                                                    "examples": [
                                                        "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                                                    ]
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "Always `cancellation_queued`: the provider is told by the worker.",
                                                    "const": "cancellation_queued",
                                                    "examples": [
                                                        "cancellation_queued"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "subscription_id",
                                                "status"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                "status": "cancellation_queued"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "`IDEMPOTENCY_KEY_MISSING`: every write needs an `Idempotency-Key` header. Send a fresh UUID per distinct operation.\n\nOn this endpoint: `SUBSCRIPTION_ALREADY_ACTIVE`: when the subscription is already cancelled, rather than silently succeeding; `error.context.subscription_id` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "IDEMPOTENCY_KEY_MISSING": {
                                        "summary": "IDEMPOTENCY_KEY_MISSING",
                                        "value": {
                                            "error": {
                                                "code": "IDEMPOTENCY_KEY_MISSING",
                                                "message": "An Idempotency-Key header is required on this endpoint.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#idempotency-key-missing",
                                                "remediation": "Re-send the request with Idempotency-Key: <uuid>; every mutation endpoint requires one.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "SUBSCRIPTION_ALREADY_ACTIVE": {
                                        "summary": "SUBSCRIPTION_ALREADY_ACTIVE",
                                        "value": {
                                            "error": {
                                                "code": "SUBSCRIPTION_ALREADY_ACTIVE",
                                                "message": "The subscriber already holds an active subscription on this project.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#subscription-already-active",
                                                "remediation": "Cancel the existing subscription first, or update its plan instead of creating a new one.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:update"
                ],
                "x-webhook-events": [
                    "subscription.cancelled"
                ],
                "x-mcp-tools": [
                    "cancel_subscription"
                ]
            }
        },
        "/v1/subscriptions/{subscription}/pause": {
            "post": {
                "operationId": "v1.subscriptions.pause",
                "description": "Suspends access: the member is removed from every linked resource, `payment_status` becomes `paused` and `paused_at` is stamped. Billing continues. Answers `202` with the outcome and emits `subscription.paused`.\n\n> **Pause suspends access, not billing.** The member's payment provider keeps charging on schedule. Subscriby settles through seven providers and only some can hold a recurring charge at all, so a pause meaning \"stop billing\" would work on some and silently not on others; access is what Subscriby controls directly, so it behaves identically everywhere. If billing must stop, cancel.\n\nOnly `active` and `trialing` subscriptions can be paused; only a `paused` one can be unpaused.",
                "summary": "Pause a subscription",
                "tags": [
                    "Subscriptions"
                ],
                "parameters": [
                    {
                        "name": "subscription",
                        "in": "path",
                        "required": true,
                        "description": "The subscription, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "202": {
                        "description": "202 with the outcome.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "subscription_id": {
                                                    "type": "string",
                                                    "description": "The purchase that was changed.",
                                                    "examples": [
                                                        "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                                                    ]
                                                },
                                                "plan_id": {
                                                    "type": "string",
                                                    "description": "Its plan.",
                                                    "examples": [
                                                        "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b"
                                                    ]
                                                },
                                                "payment_status": {
                                                    "type": "string",
                                                    "description": "The payment status after the change.",
                                                    "examples": [
                                                        "paused"
                                                    ]
                                                },
                                                "outcome": {
                                                    "type": "string",
                                                    "description": "Always `paused`.",
                                                    "const": "paused",
                                                    "examples": [
                                                        "paused"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "subscription_id",
                                                "plan_id",
                                                "payment_status",
                                                "outcome"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "payment_status": "paused",
                                                "outcome": "paused"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the subscription is neither `active` nor `trialing`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:update"
                ],
                "x-webhook-events": [
                    "subscription.paused"
                ],
                "x-mcp-tools": [
                    "pause_subscription"
                ]
            }
        },
        "/v1/subscriptions/{subscription}/unpause": {
            "post": {
                "operationId": "v1.subscriptions.unpause",
                "description": "Restores access with **fresh** invite links: the ones revoked at pause never come back. Answers `202` with the outcome (`outcome: active`) and emits `subscription.unpaused`.",
                "summary": "Unpause a subscription",
                "tags": [
                    "Subscriptions"
                ],
                "parameters": [
                    {
                        "name": "subscription",
                        "in": "path",
                        "required": true,
                        "description": "The subscription, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "202": {
                        "description": "202 with the outcome.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "subscription_id": {
                                                    "type": "string",
                                                    "description": "The purchase that was changed.",
                                                    "examples": [
                                                        "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                                                    ]
                                                },
                                                "plan_id": {
                                                    "type": "string",
                                                    "description": "Its plan.",
                                                    "examples": [
                                                        "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b"
                                                    ]
                                                },
                                                "payment_status": {
                                                    "type": "string",
                                                    "description": "The payment status after the change.",
                                                    "examples": [
                                                        "active"
                                                    ]
                                                },
                                                "outcome": {
                                                    "type": "string",
                                                    "description": "Always `active`.",
                                                    "const": "active",
                                                    "examples": [
                                                        "active"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "subscription_id",
                                                "plan_id",
                                                "payment_status",
                                                "outcome"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "payment_status": "active",
                                                "outcome": "active"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the subscription is not `paused`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:update"
                ],
                "x-webhook-events": [
                    "subscription.unpaused"
                ],
                "x-mcp-tools": [
                    "unpause_subscription"
                ]
            }
        },
        "/v1/subscriptions/{subscription}/reactivate": {
            "post": {
                "operationId": "v1.subscriptions.reactivate",
                "description": "Calls off a scheduled cancellation at the gateway and locally: the counterpart to cancel, and the win-back path. Answers `202` with the outcome (`outcome: reactivated`) and emits `subscription.reactivated`.\n\n> **Stripe only.** On every other provider, cancelling ends the agreement outright, so there is nothing left to resume; the endpoint refuses and the member has to subscribe again. Flipping the record back to active would otherwise claim a recurring subscription the provider will never charge, and the member would keep access indefinitely for free.\n\nAn already-expired subscription cannot be reactivated regardless of provider.",
                "summary": "Reactivate a subscription",
                "tags": [
                    "Subscriptions"
                ],
                "parameters": [
                    {
                        "name": "subscription",
                        "in": "path",
                        "required": true,
                        "description": "The subscription, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "202": {
                        "description": "202 with the outcome.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "subscription_id": {
                                                    "type": "string",
                                                    "description": "The purchase that was changed.",
                                                    "examples": [
                                                        "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                                                    ]
                                                },
                                                "plan_id": {
                                                    "type": "string",
                                                    "description": "Its plan.",
                                                    "examples": [
                                                        "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b"
                                                    ]
                                                },
                                                "payment_status": {
                                                    "type": "string",
                                                    "description": "The payment status after the change.",
                                                    "examples": [
                                                        "active"
                                                    ]
                                                },
                                                "outcome": {
                                                    "type": "string",
                                                    "description": "Always `reactivated`.",
                                                    "const": "reactivated",
                                                    "examples": [
                                                        "reactivated"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "subscription_id",
                                                "plan_id",
                                                "payment_status",
                                                "outcome"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "payment_status": "active",
                                                "outcome": "reactivated"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the subscription is not cancelled, has already expired, is not on Stripe, or Stripe refuses to resume it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:update"
                ],
                "x-webhook-events": [
                    "subscription.reactivated"
                ],
                "x-mcp-tools": [
                    "reactivate_subscription"
                ]
            }
        },
        "/v1/subscriptions/{subscription}/remind": {
            "post": {
                "operationId": "v1.subscriptions.remind",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/subscriptions/$SUBSCRIPTION_ID/remind \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nThe members page's nudge for a pass holder who bought a window but has not joined yet: their invite links are re-sent. Answers `200` with `reminded: true` when the connector accepted the message, and `reminded: false` when there was nothing to send: the subscription holds no window, the window has ended or been cancelled, the holder has already queued, or they cannot be reached on their connector. `false` is the dashboard's \"Nothing sent\" notice, not a fault, so it is never a `422`.\n\nThis messages a real person: read the subscription back first and do not repeat the nudge within the same window. To nudge everyone still missing from one window at once, use the [pass window remind endpoint](https://docs.subscriby.net/api/v1/reference/pass-windows).",
                "summary": "Remind a pass holder",
                "tags": [
                    "Subscriptions"
                ],
                "parameters": [
                    {
                        "name": "subscription",
                        "in": "path",
                        "required": true,
                        "description": "The subscription, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "200 with `subscription_id` and `reminded`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "subscription_id": {
                                                    "type": "string",
                                                    "description": "The purchase whose holder was nudged.",
                                                    "examples": [
                                                        "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                                                    ]
                                                },
                                                "reminded": {
                                                    "type": "boolean",
                                                    "description": "Whether the connector accepted a message; false when there was nothing to send.",
                                                    "examples": [
                                                        true
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "subscription_id",
                                                "reminded"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                "reminded": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:update"
                ],
                "x-mcp-tools": [
                    "remind_pass_holder"
                ]
            }
        },
        "/v1/subscriptions/{subscription}/grants/reissue": {
            "post": {
                "operationId": "v1.subscriptions.grants.reissue",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/subscriptions/$SUBSCRIPTION_ID/grants/reissue \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"resource_id\": \"c9e21f37-8a4b-4d56-b1e0-2f7c9d3a6e15\" }'\n```\n\nThe members page's **Refresh invite links**, for integrations. The grants the member holds are revoked (their personal invite links die) and the job that grants at purchase runs again, issuing fresh grants the bot sends to the member. `resource_id` is optional: name one resource of the plan to reissue it alone, leave it out to reissue every resource the subscription grants.\n\nAnswers `202` once the reissue is queued, where `reissued` counts the grants revoked; the fresh grants appear on the grants endpoint seconds later. Each revoked grant raises `member.resource_reissued` and each fresh one `member.resource_added`.",
                "summary": "Reissue a subscription's access",
                "tags": [
                    "Subscriptions"
                ],
                "parameters": [
                    {
                        "name": "subscription",
                        "in": "path",
                        "required": true,
                        "description": "The subscription, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ReissueSubscriptionGrantsRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "202 with `subscription_id`, `reissued` and `reissue_queued`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "subscription_id": {
                                                    "type": "string",
                                                    "description": "The purchase whose access is being reissued.",
                                                    "examples": [
                                                        "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                                                    ]
                                                },
                                                "reissued": {
                                                    "type": "integer",
                                                    "description": "How many grants were revoked; as many fresh ones follow from the queue.",
                                                    "examples": [
                                                        2
                                                    ],
                                                    "minimum": 0
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "Always `reissue_queued`: the fresh grants come from the background dispatcher.",
                                                    "const": "reissue_queued",
                                                    "examples": [
                                                        "reissue_queued"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "subscription_id",
                                                "reissued",
                                                "status"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                "reissued": 2,
                                                "status": "reissue_queued"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: when `resource_id` is not one the plan grants.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when the subscription is not active; `error.context.subscription_id` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project-subscription:update"
                ],
                "x-webhook-events": [
                    "member.resource_reissued",
                    "member.resource_added"
                ],
                "x-mcp-tools": [
                    "reissue_subscription_grants"
                ]
            }
        },
        "/v1/support/conversations": {
            "get": {
                "operationId": "v1.support-conversations.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/support/conversations?status=open\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe queue across every project the token can reach, newest activity first, 25 per page. `project_id`, `status` and `assigned_to` narrow it.",
                "summary": "List support conversations",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "project_id",
                        "in": "query",
                        "description": "Narrow the queue to a single project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "description": "Narrow to one status: `open`, `pending`, `snoozed` or `resolved`. An unknown value is refused.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "open"
                    },
                    {
                        "name": "assigned_to",
                        "in": "query",
                        "description": "Narrow to the conversations assigned to one team member, by user id.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The page to return, 1-indexed.",
                        "schema": {
                            "type": "integer",
                            "default": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100.",
                        "schema": {
                            "type": "integer",
                            "default": 25
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "An alias of `per_page`, kept for older integrations.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/SupportConversationResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `FORBIDDEN`: when the token is confined to other projects.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when `status` is not one of the four statuses; `error.context.allowed` lists them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "support-conversation:view-any"
                ],
                "x-mcp-tools": [
                    "list_support_conversations"
                ]
            }
        },
        "/v1/support/conversations/{conversation}": {
            "get": {
                "operationId": "v1.support-conversations.show",
                "description": "One thread.\n\n`member_name` is the member's display name, or \"Unknown member\" when they have not shared one. It is included so a picker built on this endpoint has something human to show; the Zapier and n8n conversation dropdowns both rely on it. Anyone who can reach the bot can open a conversation, including someone who has never paid, so `subscriber_id` may resolve to a member whose status is `lead`.\n\n`channel` is the key of the connector the member wrote through. A member who writes through two connectors has two conversations, and each reply goes back on the connector its conversation came in on.\n\n`status` is one of `open`, `pending`, `snoozed`, `resolved`. `first_response_at` is stamped **once**, on the first human reply ever in the thread: it is an SLA measure of how long the member waited for a person, not of the most recent reply, and a reopen does not reset it.\n\n`blocked: true` means inbound messages from that member are being dropped. The thread is history only, and a blocked member cannot reopen it by writing again.",
                "summary": "Get a support conversation",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "conversation",
                        "in": "path",
                        "required": true,
                        "description": "The thread, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The thread.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SupportConversationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "member_name": "Jane Doe",
                                                "channel": "telegram",
                                                "status": "open",
                                                "assigned_to_user_id": null,
                                                "subject": null,
                                                "unread_count": 2,
                                                "blocked": false,
                                                "last_message_at": "2026-08-20T10:05:00Z",
                                                "last_inbound_at": "2026-08-20T10:05:00Z",
                                                "last_outbound_at": null,
                                                "first_response_at": null,
                                                "resolved_at": null,
                                                "created_at": "2026-08-20T10:05:00Z",
                                                "updated_at": "2026-08-20T10:05:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "support-conversation:view"
                ],
                "x-mcp-tools": [
                    "get_support_conversation"
                ]
            }
        },
        "/v1/support/conversations/{conversation}/messages": {
            "get": {
                "operationId": "v1.support-conversations.messages",
                "description": "The thread's messages **oldest first**, 50 per page. `internal: true` notes are withheld unless the token also carries `support-conversation:update`: reading a private remark about a member takes the same permission as writing one.\n\n`direction` is `inbound` (from the member) or `outbound` (from your team). `author_kind` is `contact`, `creator` or `system`; `author_user_id` names the team member on an outbound reply and is `null` for inbound and system messages.\n\n`source` is the surface the message came through: `connector_chat` for a member writing to the connector's installation, `dashboard`, `api` or `mcp` for a reply from your team, and `connector_relay_dm` or `connector_relay_group` for a reply your team typed on the platform itself (into the relay's ping, or inside the thread the relay opened in a group). Messages recorded before the connector SDK carry the same three meanings under the Telegram connector's older words, `telegram_bot`, `telegram_relay_dm` and `telegram_relay_group`.\n\n`delivery_status` on an outbound message is `pending` → `sent`, or `failed` / `unreachable`. **`unreachable` means the member has blocked the bot**: the reply is stored but will never arrive, and retrying will not help. `failure_reason` carries the detail.\n\n`body` is `null` for media sent without a caption. A captioned photo puts the caption in `body` and does not create a second message. A member editing an earlier message updates the stored message in place and stamps `edited_at`; no new message is created and no event fires. Inbound messages are rate-limited per member: excess messages are dropped silently rather than queued, so a flooding member produces no burst of events.\n\nEach entry of `attachments` carries the file's `kind`, `mime`, `file_name`, `size`, `width`, `height`, `duration` and `url`.\n\n> **File ids are never returned.** A platform file id plus the bot token is enough to download the file straight from the platform, so it is treated as a credential. `url` is populated only after the file has been fetched at least once; it is `null` until then.",
                "summary": "List a conversation's messages",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "conversation",
                        "in": "path",
                        "required": true,
                        "description": "The thread, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The page to return, 1-indexed.",
                        "schema": {
                            "type": "integer",
                            "default": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Messages per page, 1 to 100.",
                        "schema": {
                            "type": "integer",
                            "default": 50
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "An alias of `per_page`, kept for older integrations.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/SupportMessageResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "6c18f7a3-2e95-4d60-b47a-c093e5182b7f",
                                                    "conversation_id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45",
                                                    "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                    "direction": "inbound",
                                                    "author_kind": "contact",
                                                    "author_user_id": null,
                                                    "type": "text",
                                                    "source": "connector_chat",
                                                    "delivery_status": "sent",
                                                    "body": "My invite link expired before I could join",
                                                    "internal": false,
                                                    "reply_to_message_id": null,
                                                    "attachments": [
                                                        {
                                                            "kind": "photo",
                                                            "mime": "image/jpeg",
                                                            "file_name": null,
                                                            "size": 84213,
                                                            "width": 1280,
                                                            "height": 720,
                                                            "duration": null,
                                                            "url": "https://static.subscriby.net/support/6c18f7a3.jpg"
                                                        }
                                                    ],
                                                    "failure_reason": null,
                                                    "edited_at": null,
                                                    "read_at": null,
                                                    "created_at": "2026-08-20T10:05:00Z"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "support-conversation:update",
                    "support-conversation:view"
                ]
            },
            "post": {
                "operationId": "v1.support-conversations.reply",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/support/conversations/$CONVERSATION_ID/messages \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"body\": \"Sorry about that. Here is a fresh invite link, valid for 24 hours.\"}'\n```\n\nAnswers `201` with the created message. `delivery_status` is `pending`: the reply has been recorded and queued, not yet delivered. Poll the message back or subscribe to `support.message.sent` rather than treating `201` as proof of receipt.\n\n**Text only.** Sending media as a reply is a dashboard-inbox feature; this API accepts a `body` of up to 4000 characters, the message ceiling on the connectors.\n\nSend `{\"body\": \"...\", \"internal\": true}` to record a private note for your team instead. Private notes are never delivered to the member and raise no webhook event.\n\nAdd `reply_to_message_id` to quote an earlier message, the way a chat client shows a threaded reply. It must name a message in **this** conversation; quoting across threads is refused, because it would put one member's words in front of another.",
                "summary": "Reply to a member",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "conversation",
                        "in": "path",
                        "required": true,
                        "description": "The thread, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "body": {
                                        "type": "string",
                                        "description": "The reply text, up to 4,000 characters, the message ceiling on the connectors. Text only; media replies are a dashboard feature."
                                    },
                                    "internal": {
                                        "type": "boolean",
                                        "description": "True records a private note for the team instead of a reply: never delivered to the member and raising no event. Defaults to false.",
                                        "default": false
                                    },
                                    "reply_to_message_id": {
                                        "type": "string",
                                        "format": "uuid",
                                        "description": "An earlier message of **this** conversation to quote, the way a chat client shows a threaded reply. A message from another thread is refused."
                                    }
                                },
                                "required": [
                                    "body"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The recorded message.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SupportMessageResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "a41d9c2e-7b53-4f08-9e16-2c8d5a7f3b90",
                                                "conversation_id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "direction": "outbound",
                                                "author_kind": "creator",
                                                "author_user_id": "4b8e2f6a-1c3d-4e5f-9a7b-8c9d0e1f2a3b",
                                                "type": "text",
                                                "source": "api",
                                                "delivery_status": "pending",
                                                "body": "Sorry about that. Here is a fresh invite link, valid for 24 hours.",
                                                "internal": false,
                                                "reply_to_message_id": null,
                                                "attachments": [],
                                                "failure_reason": null,
                                                "edited_at": null,
                                                "read_at": null,
                                                "created_at": "2026-08-20T10:12:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `body` is missing or over 4,000 characters, or `reply_to_message_id` is not a message of this conversation.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "support-conversation:update"
                ],
                "x-webhook-events": [
                    "support.message.sent"
                ],
                "x-mcp-tools": [
                    "reply_support_conversation"
                ]
            }
        },
        "/v1/projects/{project}/support/canned-replies": {
            "get": {
                "operationId": "v1.support-canned-replies.index",
                "description": "```bash\ncurl https://api.subscriby.net/v1/projects/$PROJECT_ID/support/canned-replies \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nEvery snippet on the project in the creator's order (`sort_order` ascending). The set is small by design, so the list is not paginated.",
                "summary": "List a project's saved replies",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Array of `SupportCannedReplyResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "$ref": "#/components/schemas/SupportCannedReplyResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "support-canned-reply:view-any"
                ],
                "x-mcp-tools": [
                    "list_canned_replies"
                ]
            },
            "post": {
                "operationId": "v1.support-canned-replies.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/support/canned-replies \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"title\": \"Opening hours\",\n    \"body\": \"We answer between 9 and 5, Monday to Friday.\",\n    \"shortcut\": \"hours\"\n  }'\n```\n\nAnswers `201` with the snippet and emits `support.canned_reply.created`.\n\n> **A duplicate shortcut is a 422, not a second snippet.** Shortcuts are unique per project. Sending a shortcut another saved reply on the same project already uses is refused on `shortcut`. Two different projects may both have `hours`.",
                "summary": "Create a saved reply",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreSupportCannedReplyRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The snippet.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SupportCannedReplyResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `title` or `body` is missing or out of range, `shortcut` is malformed or already used on the project, or `sort_order` is outside 0 to 999.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "support-canned-reply:create"
                ],
                "x-webhook-events": [
                    "support.canned_reply.created"
                ],
                "x-mcp-tools": [
                    "create_canned_reply"
                ]
            }
        },
        "/v1/projects/{project}/support/canned-replies/{reply}": {
            "get": {
                "operationId": "v1.support-canned-replies.show",
                "description": "One snippet. There is no `support-canned-reply:view`: a snippet is only ever read as part of the picker, so this route gates on `view-any` too. A reply is resolved **within the project**: another project's reply id is a `404 RESOURCE_NOT_FOUND`.\n\n`shortcut` is `null` when the creator never set one; the snippet is then picked from the list rather than typed.",
                "summary": "Get a saved reply",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "reply",
                        "in": "path",
                        "required": true,
                        "description": "The snippet, resolved within the project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The snippet.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SupportCannedReplyResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "1f7c9a3e-52d8-4b16-a0e4-8c3b7d29f615",
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "title": "Opening hours",
                                                "body": "We answer between 9 and 5, Monday to Friday. Anything sent outside that is picked up the next working morning.",
                                                "shortcut": "hours",
                                                "sort_order": 0,
                                                "created_at": "2026-09-06T10:05:00+00:00",
                                                "updated_at": "2026-09-06T10:05:00+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "support-canned-reply:view-any"
                ],
                "x-mcp-tools": [
                    "get_canned_reply"
                ]
            },
            "patch": {
                "operationId": "v1.support-canned-replies.update",
                "description": "```bash\ncurl -X PATCH https://api.subscriby.net/v1/projects/$PROJECT_ID/support/canned-replies/$REPLY_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"title\": \"Support hours\"}'\n```\n\nAccepts the same fields as create, all optional. **An omitted field keeps its stored value**, so a snippet can be renamed without resending its body. Send `\"shortcut\": null` to clear the shortcut. The uniqueness check ignores the snippet being edited, so resending its own shortcut is fine.\n\nAnswers `200` with the updated snippet. Replies already sent with the old wording are untouched: a saved reply is copied into a message when it is used, not referenced. Emits `support.canned_reply.updated` only when something actually changed, with a `changes` map.",
                "summary": "Update a saved reply",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "reply",
                        "in": "path",
                        "required": true,
                        "description": "The snippet, resolved within the project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateSupportCannedReplyRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The snippet, updated.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SupportCannedReplyResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when a field is out of range or the shortcut is already used on the project.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "support-canned-reply:update"
                ],
                "x-webhook-events": [
                    "support.canned_reply.updated"
                ],
                "x-mcp-tools": [
                    "update_canned_reply"
                ]
            },
            "delete": {
                "operationId": "v1.support-canned-replies.destroy",
                "description": "```bash\ncurl -X DELETE https://api.subscriby.net/v1/projects/$PROJECT_ID/support/canned-replies/$REPLY_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nReturns `204 No Content`. The snippet leaves the picker; messages sent with it stay in their threads. Emits `support.canned_reply.deleted`.",
                "summary": "Delete a saved reply",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "reply",
                        "in": "path",
                        "required": true,
                        "description": "The snippet, resolved within the project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "support-canned-reply:delete"
                ],
                "x-webhook-events": [
                    "support.canned_reply.deleted"
                ],
                "x-mcp-tools": [
                    "delete_canned_reply"
                ]
            }
        },
        "/v1/projects/{project}/support/settings": {
            "get": {
                "operationId": "v1.support-settings.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/projects/$PROJECT_ID/support/settings \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\n| Field          | Type           | Notes                                                                                                                                          |\n| -------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |\n| `enabled`      | boolean        | Whether a member's unrecognised message to the bot opens a conversation. Off stops **new** threads reaching the inbox; existing ones are kept. |\n| `relay_mode`   | string         | `owner_dm`: the platform bot messages the project owner with an inline Reply button. `forum_group`: each conversation is mirrored into its own topic of a group the bot administers. `none`: the dashboard inbox is the only surface. |\n| `agent_name`   | string or null | The name outbound replies are prefixed with so they read as coming from a person. `null` falls back to the project's default.                  |\n| `auto_reply`   | string or null | Sent to a member on their first message in a thread. `null` sends nothing.                                                                     |\n| `notify_email` | boolean        | Whether the creator is emailed about new support activity.                                                                                     |\n| `copilot_answers` | boolean | Whether Subscriby Copilot answers members' own-subscription questions and what the project's Knowledge covers in the inbox and the project bot, marked as automated; everything else still waits for a person. |\n| `copilot_portal` | boolean | Whether a signed-in member finds the same Copilot in a chat on the project's portal page. |\n\nThe keys drop the `support_` prefix the columns carry: on this endpoint everything is about support.\n\n> **The relay chat id is never exposed.** The chat the `owner_dm` relay posts to, and the group `forum_group` mirrors into, are identifiers the bot handshake writes, not settings. They do not appear here and cannot be set from here.",
                "summary": "Get a project's support settings",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The settings.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SupportSettingsResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "enabled": true,
                                                "relay_mode": "owner_dm",
                                                "agent_name": "Team Subscriby",
                                                "auto_reply": "Thanks, a person will reply within a day.",
                                                "notify_email": false,
                                                "copilot_answers": false,
                                                "copilot_portal": false,
                                                "updated_at": "2026-09-06T10:05:00+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project:view"
                ],
                "x-mcp-tools": [
                    "get_support_settings"
                ]
            },
            "patch": {
                "operationId": "v1.support-settings.update",
                "description": "```bash\ncurl -X PATCH https://api.subscriby.net/v1/projects/$PROJECT_ID/support/settings \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"relay_mode\": \"owner_dm\",\n    \"auto_reply\": \"Thanks, a person will reply within a day.\"\n  }'\n```\n\nAnswers `200` with the complete settings after the change. **Every field is optional and an omitted one keeps its stored value**, so the request above changes the relay and the auto-reply and leaves `enabled`, `agent_name` and `notify_email` alone. `support.settings.updated` fires only when at least one value actually changed, with the full settings and a `changes` map; a `PATCH` that resends the current values changes nothing and raises nothing.\n\n> **`forum_group` needs a group the bot can post into.** `forum_group` mirrors each member conversation into its own topic of a group with topics enabled. Switching the mode here does not link a group: the creator adds the project bot to such a group as an administrator (with permission to manage topics), the bot records the group itself and confirms by direct message. Until that happens, new member messages reach only the dashboard inbox. The group's id is never exposed by this endpoint.",
                "summary": "Update a project's support settings",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "project",
                        "in": "path",
                        "required": true,
                        "description": "The project, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateSupportSettingsRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The settings, updated.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SupportSettingsResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `relay_mode` is not `owner_dm`, `forum_group` or `none`, `agent_name` exceeds 60 characters, or `auto_reply` exceeds 1,000 characters.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "project:update"
                ],
                "x-webhook-events": [
                    "support.settings.updated"
                ],
                "x-mcp-tools": [
                    "update_support_settings"
                ]
            }
        },
        "/v1/support/conversations/{conversation}/resolve": {
            "post": {
                "operationId": "v1.support-conversations.resolve",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/support/conversations/$CONVERSATION_ID/resolve \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nResolving is not closing: the thread and its history are kept, and the member's next message reopens it automatically, raising `support.conversation.reopened`. Answers `200` with the thread.",
                "summary": "Resolve a support conversation",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "conversation",
                        "in": "path",
                        "required": true,
                        "description": "The thread, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The thread, resolved.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SupportConversationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "support-conversation:update"
                ],
                "x-webhook-events": [
                    "support.conversation.resolved"
                ],
                "x-mcp-tools": [
                    "resolve_support_conversation"
                ]
            }
        },
        "/v1/support/conversations/{conversation}/assign": {
            "post": {
                "operationId": "v1.support-conversations.assign",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/support/conversations/$CONVERSATION_ID/assign \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"assigned_to_user_id\": \"'\"$TEAM_USER_ID\"'\"}'\n```\n\nHands the thread to a team member. `assigned_to_user_id` must be **present**: omitting the key is refused, and sending `null` is how you clear an assignment. Answers `200` with the thread.",
                "summary": "Assign a support conversation",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "conversation",
                        "in": "path",
                        "required": true,
                        "description": "The thread, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "assigned_to_user_id": {
                                        "type": "string",
                                        "format": "uuid",
                                        "description": "The team member to hand the thread to, by user id. The key must be **present**: omitting it is refused, while sending null clears the assignment."
                                    }
                                },
                                "required": [
                                    "assigned_to_user_id"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The thread, reassigned.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SupportConversationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when the key is omitted, is not a UUID, or names no user.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "support-conversation:update"
                ],
                "x-webhook-events": [
                    "support.conversation.assigned"
                ],
                "x-mcp-tools": [
                    "assign_support_conversation"
                ]
            }
        },
        "/v1/support/conversations/{conversation}/reopen": {
            "post": {
                "operationId": "v1.support-conversations.reopen",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/support/conversations/$CONVERSATION_ID/reopen \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nPuts the conversation back to `open` and emits `support.conversation.reopened`, whatever its previous status was. A member writing back does the same thing on its own, so this is for the creator who changes their mind, or owes a follow-up before the member speaks again. Answers `200` with the thread.",
                "summary": "Reopen a support conversation",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "conversation",
                        "in": "path",
                        "required": true,
                        "description": "The thread, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The thread, open again.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SupportConversationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "support-conversation:update"
                ],
                "x-webhook-events": [
                    "support.conversation.reopened"
                ],
                "x-mcp-tools": [
                    "reopen_support_conversation"
                ]
            }
        },
        "/v1/support/conversations/{conversation}/block": {
            "post": {
                "operationId": "v1.support-conversations.block",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/support/conversations/$CONVERSATION_ID/block \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nSilences the member behind the thread: their messages to this project's bot are dropped without any notice to them, and the thread cannot reopen on inbound. Their paid access is untouched, because a block is an inbox decision and not a moderation one; use the [Members](https://docs.subscriby.net/api/v1/reference/members) endpoints to ban or kick. Idempotent and answers `200` with the thread; blocking an already-blocked contact changes nothing and emits nothing, and when the block actually flips `support.conversation.blocked` fires once.",
                "summary": "Block a support contact",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "conversation",
                        "in": "path",
                        "required": true,
                        "description": "The thread, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The thread, blocked.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SupportConversationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "support-conversation:update"
                ],
                "x-webhook-events": [
                    "support.conversation.blocked"
                ],
                "x-mcp-tools": [
                    "block_support_contact"
                ]
            }
        },
        "/v1/support/conversations/{conversation}/unblock": {
            "post": {
                "operationId": "v1.support-conversations.unblock",
                "description": "Reverses a block. Idempotent and answers `200` with the thread; `support.conversation.unblocked` fires once when the block actually flips.",
                "summary": "Unblock a support contact",
                "tags": [
                    "Support Inbox"
                ],
                "parameters": [
                    {
                        "name": "conversation",
                        "in": "path",
                        "required": true,
                        "description": "The thread, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The thread, unblocked.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/SupportConversationResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "support-conversation:update"
                ],
                "x-webhook-events": [
                    "support.conversation.unblocked"
                ],
                "x-mcp-tools": [
                    "unblock_support_contact"
                ]
            }
        },
        "/v1/teams/{team}/members": {
            "get": {
                "operationId": "v1.team-members.index",
                "description": "```bash\ncurl https://api.subscriby.net/v1/teams/$TEAM_ID/members \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe team's owner as the first row followed by every member. Not paginated: a team's collaborator list is small by construction.\n\n`email` is **omitted entirely** unless the token carries `team-member:view`. Listing who is on a team and reading how to reach them are different asks, and the fine-grained ability is what separates them. A roster-only token gets every other field and no `email` key at all: not `null`, absent.\n\nThe same `team-member:view-any` permission gates the dashboard's **Settings → Teams → Manage Members** page: only team owners and members holding the permission via their role can load it. Free-tier teams auto-assign everyone as owner, so this only matters on Growth-tier teams with multiple collaborators.",
                "summary": "List a team's members",
                "tags": [
                    "Team Members"
                ],
                "parameters": [
                    {
                        "name": "team",
                        "in": "path",
                        "required": true,
                        "description": "The team, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Array of `TeamMemberResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "$ref": "#/components/schemas/TeamMemberResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "team-member:view-any"
                ],
                "x-mcp-tools": [
                    "list_team_members"
                ]
            },
            "post": {
                "operationId": "v1.team-members.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/teams/$TEAM_ID/members \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"email\": \"newcomer@example.com\", \"role\": \"support-agent\"}'\n```\n\nAddressed by **email**, not user id: the invitee may not have a Subscriby account yet, which is what separates inviting from adding. They receive an invitation message with a link; the membership row appears when they accept.\n\n`role` is a role **code** on that team, such as `support-agent`, not a role id. Create it first with [Roles](https://docs.subscriby.net/api/v1/reference/roles) if it does not exist.\n\nAnswers `201` with the invitation summary. Emits `team.member.invited`, then `team.member.joined` when they accept.",
                "summary": "Invite a team member",
                "tags": [
                    "Team Members"
                ],
                "parameters": [
                    {
                        "name": "team",
                        "in": "path",
                        "required": true,
                        "description": "The team, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/InviteTeamMemberRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "201 with the invitation summary.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "team_id": {
                                                    "type": "string",
                                                    "description": "The team the invitation is for.",
                                                    "examples": [
                                                        "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86"
                                                    ]
                                                },
                                                "email": {
                                                    "description": "The address the invitation was sent to.",
                                                    "examples": [
                                                        "newcomer@example.com"
                                                    ]
                                                },
                                                "role": {
                                                    "description": "The role code the invitee will hold on accepting.",
                                                    "examples": [
                                                        "support-agent"
                                                    ]
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "Always `invited`: the membership appears on acceptance.",
                                                    "const": "invited",
                                                    "examples": [
                                                        "invited"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "team_id",
                                                "email",
                                                "role",
                                                "status"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                                "email": "newcomer@example.com",
                                                "role": "support-agent",
                                                "status": "invited"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: below the Growth tier; nothing changes.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when the role code is not one of the team's, or the invitee is already in the team.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "team-member:invite"
                ],
                "x-webhook-events": [
                    "team.member.invited"
                ],
                "x-mcp-tools": [
                    "invite_team_member"
                ]
            }
        },
        "/v1/teams/{team}/members/{member}": {
            "get": {
                "operationId": "v1.team-members.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/teams/$TEAM_ID/members/$USER_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nOne collaborator, with their `email`, which this route always includes because it requires `team-member:view` by definition. `404 RESOURCE_NOT_FOUND` if the user is not on the team or the team is not in the caller's visibility set.\n\n- `role_id` points at a [Role](https://docs.subscriby.net/api/v1/reference/roles) row on the same team, or `null` for the owner pseudo-row.\n- `is_owner` is `true` only for the single team creator; the owner is returned alongside the members but bypasses the membership table entirely.",
                "summary": "Get a team member",
                "tags": [
                    "Team Members"
                ],
                "parameters": [
                    {
                        "name": "team",
                        "in": "path",
                        "required": true,
                        "description": "The team, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "member",
                        "in": "path",
                        "required": true,
                        "description": "The person's place on the team, resolved by the route binder.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The membership.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/TeamMemberResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                                "name": "Priya Patel",
                                                "email": "priya@example.com",
                                                "role_id": "d05e1a83-7c46-4f29-b613-8ae407c9d251",
                                                "is_owner": false,
                                                "joined_at": "2026-04-02T14:15:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "team-member:view"
                ],
                "x-mcp-tools": [
                    "get_team_member"
                ]
            },
            "delete": {
                "operationId": "v1.team-members.destroy",
                "description": "```bash\ncurl -X DELETE https://api.subscriby.net/v1/teams/$TEAM_ID/members/$USER_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nReturns `204 No Content`. They lose access to every project and setting scoped to the team immediately; their own Subscriby account is untouched. Not gated by tier. Emits `team.member.removed`.",
                "summary": "Remove a team member",
                "tags": [
                    "Team Members"
                ],
                "parameters": [
                    {
                        "name": "team",
                        "in": "path",
                        "required": true,
                        "description": "The team, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "member",
                        "in": "path",
                        "required": true,
                        "description": "The membership, resolved by the route binder.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: for the owner, who cannot be removed.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "team-member:remove"
                ],
                "x-webhook-events": [
                    "team.member.removed"
                ],
                "x-mcp-tools": [
                    "remove_team_member"
                ]
            }
        },
        "/v1/teams/{team}/members/{member}/role": {
            "patch": {
                "operationId": "v1.team-members.update-role",
                "description": "```bash\ncurl -X PATCH https://api.subscriby.net/v1/teams/$TEAM_ID/members/$USER_ID/role \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"role\": \"manager\"}'\n```\n\nMoves a collaborator onto another of the team's roles. The team **owner** cannot be re-roled: ownership is not a membership row and carries everything unconditionally. Answers `200` with the membership and emits `team.member.role_changed`.\n\nChanging a member's role has **no dashboard equivalent**: the settings page offers invite, remove and cancel-invitation only, so this endpoint is the only way to move someone between roles without removing and re-inviting them.",
                "summary": "Change a team member's role",
                "tags": [
                    "Team Members"
                ],
                "parameters": [
                    {
                        "name": "team",
                        "in": "path",
                        "required": true,
                        "description": "The team, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "member",
                        "in": "path",
                        "required": true,
                        "description": "The membership, resolved by the route binder.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateTeamMemberRoleRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The membership after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/TeamMemberResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: below the Growth tier; nothing changes.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: for the owner, who has no role to change, or for someone who is not in the team.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when the role code is not one of the team's.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "team-member:update-role"
                ],
                "x-webhook-events": [
                    "team.member.role_changed"
                ],
                "x-mcp-tools": [
                    "update_team_member_role"
                ]
            }
        },
        "/v1/teams/{team}/invitations/{invitation}": {
            "delete": {
                "operationId": "v1.team-members.destroy-invitation",
                "description": "Requires `team-member:remove`, the same ability as removing a member, because withdrawing an invitation and removing a member revoke the same prospective access.\n\n```bash\ncurl -X DELETE https://api.subscriby.net/v1/teams/$TEAM_ID/invitations/$INVITATION_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\n> **An invitee is not a member.** Someone who has not accepted has no membership row to remove, only a pending invitation. That is why this is a separate route: removing a member and withdrawing an invitation fail on different things, and using the wrong one returns `404` rather than doing something surprising.\n\nReturns `204 No Content` and the invitation link stops working.",
                "summary": "Withdraw an invitation",
                "tags": [
                    "Team Members"
                ],
                "parameters": [
                    {
                        "name": "team",
                        "in": "path",
                        "required": true,
                        "description": "The team, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "invitation",
                        "in": "path",
                        "required": true,
                        "description": "The pending invitation, resolved within the team by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "team-member:remove"
                ],
                "x-mcp-tools": [
                    "cancel_team_invitation"
                ]
            }
        },
        "/v1/teams": {
            "get": {
                "operationId": "v1.teams.index",
                "description": "```bash\ncurl https://api.subscriby.net/v1/teams \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nEvery team the caller owns or is a member of; teams belonging to other creators are invisible. Never paginated. Useful for a re-auth flow that wants to surface a team picker before the user mints a token scoped to a specific team.",
                "summary": "List teams",
                "tags": [
                    "Teams"
                ],
                "responses": {
                    "200": {
                        "description": "Array of `TeamResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "$ref": "#/components/schemas/TeamResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "team:view-any"
                ],
                "x-mcp-tools": [
                    "list_teams"
                ]
            },
            "post": {
                "operationId": "v1.teams.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/teams \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\": \"Research Collective\"}'\n```\n\nThe caller becomes the team **owner**. Ownership is not a membership row: the owner cannot be removed from the team, cannot be re-roled, and is the only account permitted to rename or delete it.\n\nA new team starts empty. Add people with [Team Members](https://docs.subscriby.net/api/v1/reference/team-members), and give them something to hold with [Roles](https://docs.subscriby.net/api/v1/reference/roles). Answers `201` with the team and emits `team.created`.",
                "summary": "Create a team",
                "tags": [
                    "Teams"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreTeamRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The new team.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/TeamResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: below the Growth tier; nothing changes.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "team:create"
                ],
                "x-webhook-events": [
                    "team.created"
                ],
                "x-mcp-tools": [
                    "create_team"
                ]
            }
        },
        "/v1/teams/current": {
            "get": {
                "operationId": "v1.teams.current",
                "description": "```bash\ncurl https://api.subscriby.net/v1/teams/current \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nExactly the team the token is scoped to via `scope:team:<uuid>`. Zapier's connection test calls this on save to validate the bearer token.",
                "summary": "Get the current team",
                "tags": [
                    "Teams"
                ],
                "responses": {
                    "200": {
                        "description": "The team named by the token's `scope:team:` ability.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/TeamResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`TENANT_MISMATCH`: with `reason: missing_team_scope` when the token carries no team scope.\n\n`RESOURCE_NOT_FOUND`: when the scoped team no longer exists.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "team:view"
                ],
                "x-mcp-tools": [
                    "get_me"
                ]
            }
        },
        "/v1/teams/{team}": {
            "get": {
                "operationId": "v1.teams.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/teams/$TEAM_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe team if the caller belongs to it; `404 RESOURCE_NOT_FOUND` otherwise, never `403`, so foreign-team existence does not leak.",
                "summary": "Get a team",
                "tags": [
                    "Teams"
                ],
                "parameters": [
                    {
                        "name": "team",
                        "in": "path",
                        "required": true,
                        "description": "The team, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The team.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/TeamResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                                "name": "Research Collective",
                                                "owner_user_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "personal": false,
                                                "created_at": "2026-01-12T10:05:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "team:view"
                ],
                "x-mcp-tools": [
                    "get_team"
                ]
            },
            "patch": {
                "operationId": "v1.teams.update",
                "description": "```bash\ncurl -X PATCH https://api.subscriby.net/v1/teams/$TEAM_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\": \"Research Collective (EU)\"}'\n```\n\n`name` is the only mutable field. Ownership does not transfer through this endpoint, and membership moves through its own routes. Owner only. Answers `200` with the team and emits `team.updated`.",
                "summary": "Rename a team",
                "tags": [
                    "Teams"
                ],
                "parameters": [
                    {
                        "name": "team",
                        "in": "path",
                        "required": true,
                        "description": "The team, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreTeamRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The team after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/TeamResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `TEAM_TIER_REQUIRED`: below the Growth tier; nothing changes.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when the caller belongs to the team but does not own it; `error.context.team_id` names it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "team:update"
                ],
                "x-webhook-events": [
                    "team.updated"
                ],
                "x-mcp-tools": [
                    "update_team"
                ]
            },
            "delete": {
                "operationId": "v1.teams.destroy",
                "description": "```bash\ncurl -X DELETE https://api.subscriby.net/v1/teams/$TEAM_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nReturns `204 No Content` and emits `team.deleted`.\n\n> **This takes everything with it.** Deleting a team deletes every project, plan, subscription and member scoped to it. There is no restore and no soft-delete. If you only want to stop selling, archive the projects instead.",
                "summary": "Delete a team",
                "tags": [
                    "Teams"
                ],
                "parameters": [
                    {
                        "name": "team",
                        "in": "path",
                        "required": true,
                        "description": "The team, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: when the team is the caller's only one: an account with no tenant is a state nothing else in the product can produce, and an unscoped token would have nowhere to resolve to.\n\n`VALIDATION_FAILED`: when the caller is a member, not the owner: belonging to a team is not licence to dismantle it for everyone else in it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "team:delete"
                ],
                "x-webhook-events": [
                    "team.deleted"
                ],
                "x-mcp-tools": [
                    "delete_team"
                ]
            }
        },
        "/v1/tokens": {
            "get": {
                "operationId": "v1.tokens.index",
                "description": "```bash\ncurl https://api.subscriby.net/v1/tokens \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nPaginated, newest first. `per_page` accepts 1–100 and defaults to 25.",
                "summary": "List the caller's tokens",
                "tags": [
                    "Tokens"
                ],
                "parameters": [
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The caller's tokens, newest first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/TokenResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "token:view-any"
                ],
                "x-mcp-tools": [
                    "list_tokens"
                ]
            },
            "post": {
                "operationId": "v1.tokens.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/tokens \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n        \"name\": \"Nightly reconciliation\",\n        \"team_id\": \"a83f0d51-4c92-4b7e-8615-2fd9e70a3c86\",\n        \"abilities\": [\"project-subscription:view-any\", \"payment:view-any\"]\n      }'\n```\n\n`token` sits alongside `data`, not inside it, the same shape webhook endpoints use for their one-time signing secret. Store it before you do anything else; there is no endpoint that will hand it back. Minting is deliberately not offered as an MCP tool.\n\n**`team_id` is required here, and only here.** Everywhere else in v1 the team comes from the calling token's frozen scope and a `team_id` in the body is ignored. Minting is the exception: a token is created **for** a team, and you may belong to several. The minted token gets `scope:team:<team_id>` automatically. It cannot be widened later.\n\n> **A token can never mint a stronger token.** The abilities you request must be a **subset** of the abilities the calling token holds, and `token:create` is withheld unconditionally from anything minted this way.\n\nMinting used to be dashboard-only precisely so a leaked automation token could not spin up a higher-privilege one. That concern is real, and attenuation is the answer to it rather than a retreat from it: a compromised credential can produce nothing its holder could not already do directly. `token:create` is withheld on top of the subset rule for a separate reason: inherited, it would leave an unbounded ladder of tokens descending from one leak, with no single revocation that ends the chain. A human in the dashboard is not attenuated. They authenticated with a password and a second factor, not with a bearer string, so they can grant anything in the catalog.\n\nIf the calling token carries a **deprecated** coarse ability, it may still mint the precise abilities that ability covers; the split does not shrink what an existing token can delegate.\n\nAsking for more than you hold returns `422`; `context.abilities` echoes back what you asked for, not what was refused, and the refused ones are named in `message`:\n\n```json\n{\n  \"error\": {\n    \"code\": \"VALIDATION_FAILED\",\n    \"message\": \"A token cannot grant abilities it does not hold: coupon:delete, project:delete.\",\n    \"context\": {\n      \"abilities\": [\"coupon:delete\", \"project:delete\", \"project:view-any\"]\n    }\n  }\n}\n```\n\nA retired ability keeps working on tokens that already carry it, but no new token can be given one. This is a field-level failure, so every offending entry in the array is reported at once under `fields`, and the message names the replacements; an ability that is simply unknown gets a different message pointing at the catalog, because a typo and a retirement need different fixes:\n\n```json\n{\n  \"error\": {\n    \"code\": \"VALIDATION_FAILED\",\n    \"message\": \"webhook-endpoint:manage is retired and cannot be granted to a new token. Use webhook-delivery:retry, webhook-delivery:view-any, webhook-endpoint:create, webhook-endpoint:delete, webhook-endpoint:update, webhook-endpoint:view, webhook-endpoint:view-any instead.\",\n    \"fields\": {\n      \"abilities.0\": [\n        \"webhook-endpoint:manage is retired and cannot be granted to a new token. Use webhook-delivery:retry, webhook-delivery:view-any, webhook-endpoint:create, webhook-endpoint:delete, webhook-endpoint:update, webhook-endpoint:view, webhook-endpoint:view-any instead.\"\n      ]\n    }\n  }\n}\n```",
                "summary": "Mint a token",
                "tags": [
                    "Tokens"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreTokenRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The token resource plus the plaintext, as a 201.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/TokenResource"
                                        },
                                        "token": {
                                            "type": "string",
                                            "description": "The plaintext token, `sbt_<env>_<id>_<secret>`, returned exactly once. Store it before anything else.",
                                            "examples": [
                                                "sbt_live_1902_9f2c…"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "token"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "1902",
                                                "name": "Nightly reconciliation",
                                                "abilities": [
                                                    "project-subscription:view-any",
                                                    "payment:view-any"
                                                ],
                                                "scopes": {
                                                    "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                                    "project_ids": []
                                                },
                                                "abilities_count": 2,
                                                "last_used_at": null,
                                                "expires_at": null,
                                                "created_at": "2026-08-31T11:42:00Z"
                                            },
                                            "token": "sbt_live_1902_9f2c…"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when a requested ability is not held by the calling token, `token:create` is requested, `team_id` is not a team the caller owns or belongs to, an ability is retired or unknown, or `abilities` is empty.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "token:create"
                ],
                "x-mcp-tools": [
                    "create_token"
                ]
            }
        },
        "/v1/tokens/{token}": {
            "get": {
                "operationId": "v1.tokens.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/tokens/$TOKEN_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nOne of the caller's tokens, without its value.\n\n- `id` is an **integer** serialised as a string, the one identifier in the platform that is not a UUID. See [Identifiers](https://docs.subscriby.net/api/v1#identifiers).\n- `abilities` is the gate strings only. Scope tuples (`scope:team:…`, `scope:project:…`) are split out into `scopes` for readability, so `abilities_count` counts real permissions rather than bookkeeping.\n- The plaintext value is **never** returned here. Lose it and the only recovery is to revoke the token and mint another.",
                "summary": "Get a token",
                "tags": [
                    "Tokens"
                ],
                "parameters": [
                    {
                        "name": "token",
                        "in": "path",
                        "required": true,
                        "description": "One of the caller's tokens, resolved by the route binder.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The token resource.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/TokenResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "1284",
                                                "name": "Zapier production",
                                                "abilities": [
                                                    "project:view-any",
                                                    "project-subscription-plan:view"
                                                ],
                                                "scopes": {
                                                    "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                                    "project_ids": [
                                                        "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                                    ]
                                                },
                                                "abilities_count": 2,
                                                "last_used_at": "2026-05-18T09:15:00Z",
                                                "expires_at": null,
                                                "created_at": "2026-05-01T10:05:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "token:view"
                ],
                "x-mcp-tools": [
                    "get_token"
                ]
            },
            "delete": {
                "operationId": "v1.tokens.destroy",
                "description": "```bash\ncurl -X DELETE https://api.subscriby.net/v1/tokens/$TOKEN_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nReturns `204 No Content`. Revocation is immediate: in-flight requests already authenticated will finish, and the next one fails.",
                "summary": "Revoke a token",
                "tags": [
                    "Tokens"
                ],
                "parameters": [
                    {
                        "name": "token",
                        "in": "path",
                        "required": true,
                        "description": "One of the caller's tokens, resolved by the route binder.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.\n\nOn this endpoint: `RESOURCE_NOT_FOUND`: when no token with that id belongs to the authenticated user.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "RESOURCE_NOT_FOUND": {
                                        "summary": "RESOURCE_NOT_FOUND",
                                        "value": {
                                            "error": {
                                                "code": "RESOURCE_NOT_FOUND",
                                                "message": "The requested resource could not be found.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                                "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: with `token: self-revoke blocked` when you tried to revoke the exact row you are authenticating with. Revoke it from the dashboard, or from another token on the same account. This exists so an automation cannot lock itself out mid-run and leave the failure looking like a network fault.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "token:delete"
                ],
                "x-mcp-tools": [
                    "revoke_token"
                ]
            }
        },
        "/v1/me/transaction-fees": {
            "get": {
                "operationId": "v1.me.transaction-fees.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/me/transaction-fees?month=2026-10&channel=metered\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nPages the ledger, the most recently incurred first. `month` keeps one calendar month (`YYYY-MM`, UTC) and wins over `from` and `to`, which bound the window by instant; `project_id` keeps one project's lines; `channel` is `connect_at_source` or `metered`; `kind` is `payment_fee`, `access_code_fee`, `trial_usage`, `outage_emails` or `processing_recovery`. Sort with `sort_by` (`occurred_at` by default, or `fee_amount`, `units`, `kind`, `channel`, `created_at`) and `sort_direction`.\n\nEach row names what the fee was for and, for a payment's fee, the project, the member, the purchase and the payment it was priced from with the gross amount, the currency and the rate applied. `fee_amount` is in `fee_currency`, your billing currency; `units` are the cents the meter counted, zero on a fee taken at source. A line of a different kind (a trial's waived fees, a recovery's emails, an invoice's processing recovery) carries its `meter_identifier` and no payment.",
                "summary": "List your transaction fees",
                "tags": [
                    "Transaction Fees"
                ],
                "parameters": [
                    {
                        "name": "month",
                        "in": "query",
                        "description": "Keep only the lines of one calendar month, as `YYYY-MM` in UTC, such as `2026-10`; wins over `from` and `to`.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "description": "Keep only lines incurred at or after this instant, ISO 8601.",
                        "schema": {
                            "type": "string",
                            "format": "date-time"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "description": "Keep only lines incurred before this instant, ISO 8601.",
                        "schema": {
                            "type": "string",
                            "format": "date-time"
                        }
                    },
                    {
                        "name": "project_id",
                        "in": "query",
                        "description": "Keep only the lines earned on this project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "channel",
                        "in": "query",
                        "description": "Keep only lines collected one way: `connect_at_source` (deducted from the member's payment by Stripe Connect) or `metered` (billed on your own Subscriby invoice).",
                        "schema": {
                            "$ref": "#/components/schemas/PlatformFeeChannel"
                        }
                    },
                    {
                        "name": "kind",
                        "in": "query",
                        "description": "Keep only lines of one kind: `payment_fee`, `access_code_fee`, `trial_usage`, `outage_emails` or `processing_recovery`.",
                        "schema": {
                            "$ref": "#/components/schemas/PlatformFeeKind"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 25.",
                        "schema": {
                            "type": "integer",
                            "default": 25,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/TransactionFeeResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL.",
                                                    "examples": [
                                                        "https://api.subscriby.net/v1/me/transaction-fees?page=1"
                                                    ]
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL.",
                                                    "examples": [
                                                        "https://api.subscriby.net/v1/me/transaction-fees?page=1"
                                                    ]
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page.",
                                                    "examples": [
                                                        null
                                                    ]
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page.",
                                                    "examples": [
                                                        null
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs.",
                                                    "examples": [
                                                        "https://api.subscriby.net/v1/me/transaction-fees"
                                                    ]
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "examples": [
                                                        25
                                                    ],
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "examples": [
                                                        1
                                                    ],
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "7d2f9b4e-3c1a-4e5b-9f6d-2a8b7c6d5e4f",
                                                    "kind": "payment_fee",
                                                    "kind_label": "Payment Fee",
                                                    "channel": "metered",
                                                    "channel_label": "Billed on Invoice",
                                                    "provider": "paypal",
                                                    "project_id": "0f1e2d3c-4b5a-4968-8776-655443322110",
                                                    "project_name": "Acme Club",
                                                    "member_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
                                                    "member_name": "Jane Fox",
                                                    "subscription_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                                                    "payment_id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                                                    "gross_amount": "39.0000",
                                                    "gross_currency": "USD",
                                                    "rate_percent": "3.0000",
                                                    "fee_amount": "1.1700",
                                                    "fee_currency": "USD",
                                                    "units": 117,
                                                    "meter_identifier": null,
                                                    "invoice_id": "in_1QExampleInvoice00",
                                                    "invoiced_at": "2026-11-01T06:30:12+00:00",
                                                    "occurred_at": "2026-10-14T18:02:41+00:00",
                                                    "created_at": "2026-10-14T18:02:41+00:00"
                                                }
                                            ],
                                            "links": {
                                                "first": "https://api.subscriby.net/v1/me/transaction-fees?page=1",
                                                "last": "https://api.subscriby.net/v1/me/transaction-fees?page=1",
                                                "prev": null,
                                                "next": null
                                            },
                                            "meta": {
                                                "current_page": 1,
                                                "from": 1,
                                                "last_page": 1,
                                                "path": "https://api.subscriby.net/v1/me/transaction-fees",
                                                "per_page": 25,
                                                "to": 1,
                                                "total": 1
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `month` is not `YYYY-MM`, a bound is not a date, `project_id` is not an id, or `channel` or `kind` is not one of the words above.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-mcp-tools": [
                    "list_transaction_fees"
                ]
            }
        },
        "/v1/me/transaction-fees/summary": {
            "get": {
                "operationId": "v1.me.transaction-fees.summary",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/me/transaction-fees/summary?month=2026-10\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nAdds up one calendar month, the current one when `month` is left out. `total_fee` is every line; `at_source_fee` is what Stripe Connect deducted from members' payments and never invoiced; `metered_fee` is what reached the usage meter, the figure to hold against that month's Transaction Fees line on your Subscriby invoice, split into `invoiced_fee` (a paid invoice has collected it) and `awaiting_invoice_fee` (it lands on the next one). `by_kind` lists the month per kind of fee, `by_project` per project largest first (the fees no project carries pool under a null id), and `invoices` the Subscriby invoices that billed the month's metered lines. Pass `project_id` to add up one project alone; `by_project` is then empty.",
                "summary": "Get a month's fee summary",
                "tags": [
                    "Transaction Fees"
                ],
                "parameters": [
                    {
                        "name": "month",
                        "in": "query",
                        "description": "The calendar month to add up, as `YYYY-MM` in UTC, such as `2026-10`; the current month when left out.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "project_id",
                        "in": "query",
                        "description": "Add up one project's lines alone; every project when left out, in which case the per-project shares are returned too.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The month's totals per channel, kind, project and invoice.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/TransactionFeeSummaryResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "period_start": "2026-10-01",
                                                "period_end": "2026-11-01",
                                                "currency": "USD",
                                                "total_fee": "48.5100",
                                                "at_source_fee": "31.2000",
                                                "metered_fee": "17.3100",
                                                "metered_units": 1731,
                                                "invoiced_fee": "12.4800",
                                                "awaiting_invoice_fee": "4.8300",
                                                "rows": 41,
                                                "by_kind": [
                                                    {
                                                        "kind": "payment_fee",
                                                        "label": "Payment Fee",
                                                        "fee": "46.1100",
                                                        "units": 1491,
                                                        "rows": 38
                                                    },
                                                    {
                                                        "kind": "access_code_fee",
                                                        "label": "Access Code Fee",
                                                        "fee": "1.1700",
                                                        "units": 117,
                                                        "rows": 1
                                                    },
                                                    {
                                                        "kind": "processing_recovery",
                                                        "label": "Processing Recovery",
                                                        "fee": "1.2300",
                                                        "units": 123,
                                                        "rows": 2
                                                    }
                                                ],
                                                "by_project": [
                                                    {
                                                        "project_id": "0f1e2d3c-4b5a-4968-8776-655443322110",
                                                        "name": "Acme Club",
                                                        "fee": "47.2800",
                                                        "rows": 39
                                                    },
                                                    {
                                                        "project_id": null,
                                                        "name": null,
                                                        "fee": "1.2300",
                                                        "rows": 2
                                                    }
                                                ],
                                                "invoices": [
                                                    {
                                                        "invoice_id": "in_1QExampleInvoice00",
                                                        "fee": "12.4800",
                                                        "units": 1248,
                                                        "rows": 27,
                                                        "invoiced_at": "2026-11-01T06:30:12+00:00"
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `month` is not `YYYY-MM` or `project_id` is not an id.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-mcp-tools": [
                    "get_transaction_fee_summary"
                ]
            }
        },
        "/v1/webhook-deliveries": {
            "get": {
                "operationId": "v1.webhook-deliveries.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/webhook-deliveries?status=dead\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe team's deliveries across every endpoint, **newest first**, 25 per page (`per_page` 1 to 100; `limit` is accepted as an alias).",
                "summary": "List webhook deliveries",
                "tags": [
                    "Webhook Deliveries"
                ],
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "description": "One of the log's tabs: `all` (the default), `pending`, `delivered`, `failed` or `dead`. A tab rather than a raw status, so an omitted value lists every row instead of quietly matching nothing. Anything else is refused.",
                        "schema": {
                            "anyOf": [
                                {
                                    "$ref": "#/components/schemas/WebhookDeliveryFilter"
                                },
                                {
                                    "type": "null"
                                }
                            ]
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 15.",
                        "schema": {
                            "type": "integer",
                            "default": 15,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Legacy alias of `per_page`, kept for clients that predate it. `per_page` wins when both are sent.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The tenant's deliveries on that tab, newest first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/WebhookDeliveryResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: naming `status` when it is not one of the five tabs.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "webhook-delivery:view-any"
                ],
                "x-mcp-tools": [
                    "list_webhook_deliveries"
                ]
            }
        },
        "/v1/webhook-deliveries/{delivery}": {
            "get": {
                "operationId": "v1.webhook-deliveries.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/webhook-deliveries/$DELIVERY_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nOne delivery. Another team's delivery is a `404 RESOURCE_NOT_FOUND`, never a `403`.\n\n| Field              | Type            | Notes                                                                                                                                      |\n| ------------------ | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |\n| `event`            | string          | The event name, as in the [catalog](https://docs.subscriby.net/api/v1/reference/webhook-events).                                              |\n| `event_id`         | string          | The 26-character ULID the envelope's `id` carries without its `evt_` prefix; also the `SB-Event-Id` header your handler received.          |\n| `status`           | string          | `pending`, `delivered`, `failed` or `dead`. See below.                                                                                     |\n| `attempts`         | integer         | Posts made so far. Reset to `0` by a retry.                                                                                                |\n| `response_status`  | integer or null | The HTTP status your endpoint returned on the last attempt; `null` before the first post or after a transport failure.                     |\n| `response_excerpt` | string or null  | The start of the response body, or the transport error.                                                                                    |\n| `payload`          | object          | The full [event envelope](https://docs.subscriby.net/webhooks/v1/events) that was, or would have been, posted, so a consumer can be debugged against it exactly. |\n| `next_attempt_at`  | string or null  | When the worker will post a `failed` row again.                                                                                            |\n| `delivered_at`     | string or null  | Stamped on the first 2xx.                                                                                                                  |\n| `dead_lettered_at` | string or null  | Stamped when the ladder ran out.                                                                                                           |\n\nThere is no `updated_at`: a delivery only moves forward through its statuses, and the three timestamps say when each transition happened.\n\nA row is born `pending`, becomes `failed` after a non-2xx or transport error while retries remain, `delivered` on the first 2xx, and `dead` once the ladder is exhausted or the endpoint vanished. `delivered` and `dead` are final until a retry resets the row to `pending`.\n\n> **`payload` discloses nothing new.** The envelope is what your own endpoint already received, or would have had it answered. Reading it needs `webhook-delivery:view-any`, and the tenant scope reaches a delivery only through an endpoint of the token's team.",
                "summary": "Get a webhook delivery",
                "tags": [
                    "Webhook Deliveries"
                ],
                "parameters": [
                    {
                        "name": "delivery",
                        "in": "path",
                        "required": true,
                        "description": "The delivery, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The delivery with the envelope its endpoint received.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/WebhookDeliveryResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "34f1d78e-05a2-4b69-8c3d-7e921ab06f45",
                                                "endpoint_id": "c62a08f4-1b7d-4e35-9860-a37f5d21e0b9",
                                                "event": "subscription.created",
                                                "event_id": "01HXZ3Q8M7Y2K4N6P9R1T3V5W7",
                                                "status": "failed",
                                                "attempts": 2,
                                                "response_status": 500,
                                                "response_excerpt": "upstream unavailable",
                                                "payload": {
                                                    "id": "evt_01HXZ3Q8M7Y2K4N6P9R1T3V5W7",
                                                    "type": "subscription.created",
                                                    "created_at": "2026-09-06T10:05:00+00:00",
                                                    "api_version": "2026-05-01",
                                                    "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                    "data": {
                                                        "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                        "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                        "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                                                    }
                                                },
                                                "next_attempt_at": "2026-09-06T10:15:00+00:00",
                                                "delivered_at": null,
                                                "dead_lettered_at": null,
                                                "created_at": "2026-09-06T10:05:00+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "webhook-delivery:view-any"
                ],
                "x-mcp-tools": [
                    "get_webhook_delivery"
                ]
            }
        },
        "/v1/webhook-deliveries/retry-dead": {
            "post": {
                "operationId": "v1.webhook-deliveries.retry-dead",
                "description": "Once the consumer is fixed, replay everything the team dead-lettered since an instant in one call.\n\n```bash\ncurl -X POST https://api.subscriby.net/v1/webhook-deliveries/retry-dead \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"since\": \"2026-09-05T22:00:00Z\"}'\n```\n\n`retried` is how many rows were reset and queued. Only `dead` rows are touched: a `failed` row is still on its ladder and will be posted again on its own. The replay is capped at 500 rows per call so one request after a long outage cannot flood the queue or the target; call it again if the count comes back at the ceiling.\n\nEach replayed row posts its event again, so confirm the consumer is healthy first; see [replaying bulk dead deliveries](https://docs.subscriby.net/webhooks/v1/retries-and-delivery#replaying-bulk-dead-deliveries).",
                "summary": "Retry every recent dead delivery",
                "tags": [
                    "Webhook Deliveries"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/RetryDeadWebhookDeliveriesRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "How many rows were re-queued and the instant the window opened at.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "retried": {
                                                    "type": "integer",
                                                    "description": "How many dead rows were reset to pending and queued, at most 500 per call.",
                                                    "examples": [
                                                        17
                                                    ],
                                                    "minimum": 0
                                                },
                                                "since": {
                                                    "type": "string",
                                                    "description": "The instant the window opened at, ISO 8601: as sent, or 24 hours ago when omitted.",
                                                    "examples": [
                                                        "2026-09-05T22:00:00+00:00"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "retried",
                                                "since"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "retried": 17,
                                                "since": "2026-09-05T22:00:00+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `since` is malformed or in the future.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "webhook-delivery:retry"
                ],
                "x-mcp-tools": [
                    "retry_dead_webhook_deliveries"
                ]
            }
        },
        "/v1/webhook-deliveries/{delivery}/retry": {
            "post": {
                "operationId": "v1.webhook-deliveries.retry",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/webhook-deliveries/$DELIVERY_ID/retry \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nAnswers `200` with the row **pending again**: `attempts` back to `0`, `response_status`, `response_excerpt` and `dead_lettered_at` cleared, and the worker queued. The delivery log then shows the replay's own outcome rather than the original failure's. A retry re-posts the **original** event to its endpoint; nothing new is raised about the replay itself.\n\n> **Only `failed` and `dead` rows can be retried.** Resetting a delivered row would post the event to your server a second time. The dashboard hides its retry button behind the same rule, but a row can be delivered between a render and a click, and the API has no button at all.",
                "summary": "Retry a webhook delivery",
                "tags": [
                    "Webhook Deliveries"
                ],
                "parameters": [
                    {
                        "name": "delivery",
                        "in": "path",
                        "required": true,
                        "description": "The delivery, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The delivery, pending again.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/WebhookDeliveryResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: for a `pending` or `delivered` row, with the message *Only failed or dead-lettered deliveries can be retried.*",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "webhook-delivery:retry"
                ],
                "x-mcp-tools": [
                    "retry_webhook_delivery"
                ]
            }
        },
        "/v1/webhook-endpoints": {
            "get": {
                "operationId": "v1.webhook-endpoints.index",
                "description": "```bash\ncurl https://api.subscriby.net/v1/webhook-endpoints \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe team's endpoints without their secrets, paged with `page` and `per_page`.",
                "summary": "List webhook endpoints",
                "tags": [
                    "Webhook Endpoints"
                ],
                "parameters": [
                    {
                        "name": "page",
                        "in": "query",
                        "description": "The 1-based page to return. A page past the last answers an empty `data` array with `meta.total` still filled, so a loop can stop without guessing.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Rows per page, 1 to 100. A higher value clamps to the cap silently. Defaults to 15.",
                        "schema": {
                            "type": "integer",
                            "default": 15,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "The column to order by. Defaults to `created_at`; a column the endpoint does not offer falls back to the default rather than failing.",
                        "schema": {
                            "type": "string",
                            "default": "created_at"
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "`asc` or `desc`. Defaults to `desc`.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The team's endpoints without their secrets.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items on this page.",
                                            "items": {
                                                "$ref": "#/components/schemas/WebhookEndpointResource"
                                            }
                                        },
                                        "links": {
                                            "type": "object",
                                            "description": "Links to the first, last, previous and next pages.",
                                            "properties": {
                                                "first": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The first page's URL."
                                                },
                                                "last": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The last page's URL."
                                                },
                                                "prev": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The previous page's URL; null on the first page."
                                                },
                                                "next": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The next page's URL; null on the last page."
                                                }
                                            },
                                            "required": [
                                                "first",
                                                "last",
                                                "prev",
                                                "next"
                                            ]
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "The paging counters for this page.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned, 1-indexed.",
                                                    "minimum": 1
                                                },
                                                "from": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The 1-indexed position of this page's first item across every page; null when the page is empty.",
                                                    "minimum": 1
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "How many pages there are.",
                                                    "minimum": 1
                                                },
                                                "links": {
                                                    "type": "array",
                                                    "description": "Generated paginator links.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One pager link.",
                                                        "properties": {
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The page's URL; null for the ellipsis and the disabled arrows."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The link's label: a page number, the previous or next arrow, or an ellipsis."
                                                            },
                                                            "active": {
                                                                "type": "boolean",
                                                                "description": "Whether this link is the current page."
                                                            }
                                                        },
                                                        "required": [
                                                            "url",
                                                            "label",
                                                            "active"
                                                        ]
                                                    }
                                                },
                                                "path": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Base path for paginator generated URLs."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Number of items shown per page.",
                                                    "minimum": 0
                                                },
                                                "to": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Number of the last item in the slice.",
                                                    "minimum": 1
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total number of items being paginated.",
                                                    "minimum": 0
                                                }
                                            },
                                            "required": [
                                                "current_page",
                                                "from",
                                                "last_page",
                                                "links",
                                                "path",
                                                "per_page",
                                                "to",
                                                "total"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "webhook-endpoint:view-any"
                ],
                "x-mcp-tools": [
                    "list_webhook_endpoints"
                ]
            },
            "post": {
                "operationId": "v1.webhook-endpoints.store",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/webhook-endpoints \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Zapier trigger\",\n    \"url\": \"https://hooks.zapier.com/hooks/catch/...\",\n    \"events\": [\"subscription.created\", \"payment.succeeded\"]\n  }'\n```\n\nAnswers `201` with the endpoint and, at the top level beside `data`, the plaintext signing `secret`.\n\n> **The secret appears once.** The plaintext `secret` (prefixed `whsec_`) appears at the top level of the response **only** here and on rotate-secret. Subsequent reads never surface it; copy it into your consumer's secret storage immediately.",
                "summary": "Register a webhook endpoint",
                "tags": [
                    "Webhook Endpoints"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StoreWebhookEndpointRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "201 with the resource and a top-level `secret`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/WebhookEndpointResource"
                                        },
                                        "secret": {
                                            "type": "string",
                                            "description": "The plaintext signing secret, `whsec_…`, returned once. Verify every delivery's `SB-Signature` with it.",
                                            "examples": [
                                                "whsec_a1b2c3..."
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "secret"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "c62a08f4-1b7d-4e35-9860-a37f5d21e0b9",
                                                "name": "Zapier trigger",
                                                "url": "https://hooks.zapier.com/hooks/catch/...",
                                                "project_id": null,
                                                "events": [
                                                    "subscription.created",
                                                    "payment.succeeded"
                                                ],
                                                "is_active": true,
                                                "disabled_at": null,
                                                "allowed_ips": null,
                                                "failure_count": 0,
                                                "consecutive_failures": 0,
                                                "last_success_at": null,
                                                "last_failure_at": null,
                                                "created_at": "2026-05-18T10:05:00Z",
                                                "updated_at": "2026-05-18T10:05:00Z"
                                            },
                                            "secret": "whsec_a1b2c3..."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`TENANT_MISMATCH`: with `reason: missing_team_scope` when the token carries no team scope.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `url` is not `https://`, points at a private or reserved host, or exceeds 2,048 characters; when `events` is empty or names an unknown event; when `allowed_ips` holds an invalid address or range; when `name` is outside 3 to 100 characters.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "webhook-endpoint:create"
                ],
                "x-mcp-tools": [
                    "create_webhook_endpoint"
                ]
            }
        },
        "/v1/webhook-endpoints/{endpoint}": {
            "get": {
                "operationId": "v1.webhook-endpoints.show",
                "description": "```bash\ncurl https://api.subscriby.net/v1/webhook-endpoints/$ENDPOINT_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe endpoint and its delivery health. The signing secret is never part of it; it exists in the create and rotate-secret responses only.\n\n`disabled_at` populates when Subscriby auto-disables an endpoint after too many consecutive failures, or when the creator pauses it. `last_success_at` / `last_failure_at` track the most recent delivery outcomes. `project_id` is `null` for team-wide endpoints.",
                "summary": "Get a webhook endpoint",
                "tags": [
                    "Webhook Endpoints"
                ],
                "parameters": [
                    {
                        "name": "endpoint",
                        "in": "path",
                        "required": true,
                        "description": "The endpoint, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The endpoint and its delivery health, without its secret.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/WebhookEndpointResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "id": "c62a08f4-1b7d-4e35-9860-a37f5d21e0b9",
                                                "name": "Zapier trigger",
                                                "url": "https://hooks.zapier.com/hooks/catch/...",
                                                "project_id": null,
                                                "events": [
                                                    "subscription.created",
                                                    "payment.succeeded"
                                                ],
                                                "is_active": true,
                                                "disabled_at": null,
                                                "allowed_ips": null,
                                                "failure_count": 0,
                                                "consecutive_failures": 0,
                                                "last_success_at": null,
                                                "last_failure_at": null,
                                                "created_at": "2026-05-18T10:05:00Z",
                                                "updated_at": "2026-05-18T10:05:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "webhook-endpoint:view"
                ],
                "x-mcp-tools": [
                    "get_webhook_endpoint"
                ]
            },
            "delete": {
                "operationId": "v1.webhook-endpoints.destroy",
                "description": "```bash\ncurl -X DELETE https://api.subscriby.net/v1/webhook-endpoints/$ENDPOINT_ID \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nReturns `204 No Content`. The endpoint's delivery log stays readable.",
                "summary": "Delete a webhook endpoint",
                "tags": [
                    "Webhook Endpoints"
                ],
                "parameters": [
                    {
                        "name": "endpoint",
                        "in": "path",
                        "required": true,
                        "description": "The endpoint, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `FORBIDDEN`: when the caller neither registered the endpoint nor owns the team.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "webhook-endpoint:delete"
                ],
                "x-mcp-tools": [
                    "delete_webhook_endpoint"
                ]
            }
        },
        "/v1/webhook-endpoints/{endpoint}/rotate-secret": {
            "post": {
                "operationId": "v1.webhook-endpoints.rotate-secret",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/webhook-endpoints/$ENDPOINT_ID/rotate-secret \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nAnswers `200` with the endpoint and a brand-new `secret` alongside `data`. The old secret is revoked immediately: deploy the new one to your handler before calling this endpoint.",
                "summary": "Rotate a webhook endpoint's secret",
                "tags": [
                    "Webhook Endpoints"
                ],
                "parameters": [
                    {
                        "name": "endpoint",
                        "in": "path",
                        "required": true,
                        "description": "The endpoint, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The resource with the new plaintext `secret`, once.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/WebhookEndpointResource"
                                        },
                                        "secret": {
                                            "type": "string",
                                            "description": "The new plaintext signing secret, `whsec_…`, returned once."
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "secret"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `FORBIDDEN`: when the caller neither registered the endpoint nor owns the team.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "webhook-endpoint:update"
                ],
                "x-mcp-tools": [
                    "rotate_webhook_endpoint_secret"
                ]
            }
        },
        "/v1/webhook-endpoints/{endpoint}/test": {
            "post": {
                "operationId": "v1.webhook-endpoints.test",
                "description": "Enqueues a synthetic `subscription.created`-shaped delivery against the endpoint and answers `202 Accepted`. The row is handed to the delivery worker immediately, so it shows up in **Settings → Webhook Deliveries** and moves to `delivered` or `failed` as soon as your handler answers. Rate-limited to 5 fires per minute per endpoint.",
                "summary": "Test-fire a webhook endpoint",
                "tags": [
                    "Webhook Endpoints"
                ],
                "parameters": [
                    {
                        "name": "endpoint",
                        "in": "path",
                        "required": true,
                        "description": "The endpoint, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "202": {
                        "description": "202 with the new delivery's id and status.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The response's payload.",
                                            "properties": {
                                                "delivery_id": {
                                                    "description": "The delivery row to read the outcome from.",
                                                    "examples": [
                                                        "34f1d78e-05a2-4b69-8c3d-7e921ab06f45"
                                                    ]
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "Always `pending` at this point; read the delivery for what happened.",
                                                    "enum": [
                                                        "pending",
                                                        "delivered",
                                                        "failed",
                                                        "dead"
                                                    ],
                                                    "examples": [
                                                        "pending"
                                                    ]
                                                },
                                                "enqueued_at": {
                                                    "type": "string",
                                                    "description": "When the row was handed to the worker, ISO 8601.",
                                                    "examples": [
                                                        "2026-05-18T10:05:00Z"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "delivery_id",
                                                "status",
                                                "enqueued_at"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": {
                                                "delivery_id": "34f1d78e-05a2-4b69-8c3d-7e921ab06f45",
                                                "status": "pending",
                                                "enqueued_at": "2026-05-18T10:05:00Z"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `FORBIDDEN`: when the caller neither registered the endpoint nor owns the team.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "webhook-endpoint:update"
                ],
                "x-mcp-tools": [
                    "test_webhook_endpoint"
                ]
            }
        },
        "/v1/webhook-endpoints/{endpoint}/pause": {
            "post": {
                "operationId": "v1.webhook-endpoints.pause",
                "description": "```bash\ncurl -X POST https://api.subscriby.net/v1/webhook-endpoints/$ENDPOINT_ID/pause \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\" \\\n  -H \"Idempotency-Key: $(uuidgen)\"\n```\n\nThe dashboard's on/off switch, off. A paused endpoint keeps its secret, its event subscriptions and its delivery log, but events raised while it is paused are **not** queued for it and are not replayed on resume; use the [deliveries API](https://docs.subscriby.net/api/v1/reference/webhook-deliveries) to replay rows that dead-lettered before the pause. Answers `200` with the endpoint; idempotent, pausing a paused endpoint changes nothing.",
                "summary": "Pause a webhook endpoint",
                "tags": [
                    "Webhook Endpoints"
                ],
                "parameters": [
                    {
                        "name": "endpoint",
                        "in": "path",
                        "required": true,
                        "description": "The endpoint, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The endpoint, paused.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/WebhookEndpointResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `FORBIDDEN`: when the caller neither registered the endpoint nor owns the team.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "webhook-endpoint:update"
                ],
                "x-mcp-tools": [
                    "pause_webhook_endpoint"
                ]
            }
        },
        "/v1/webhook-endpoints/{endpoint}/resume": {
            "post": {
                "operationId": "v1.webhook-endpoints.resume",
                "description": "The switch, on. Resuming also clears the consecutive-failure streak, so a target that was fixed while paused is not disabled again on its first miss. Answers `200` with the endpoint; idempotent.",
                "summary": "Resume a webhook endpoint",
                "tags": [
                    "Webhook Endpoints"
                ],
                "parameters": [
                    {
                        "name": "endpoint",
                        "in": "path",
                        "required": true,
                        "description": "The endpoint, resolved by the route binder.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with `Idempotent-Replay: true`), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a4ae-6c02-7b5c-9f51-c5f0da5e2f12"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The endpoint, active.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "description": "The response's payload.",
                                            "$ref": "#/components/schemas/WebhookEndpointResource"
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/IdempotencyKeyMissing"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.\n\nOn this endpoint: `FORBIDDEN`: when the caller neither registered the endpoint nor owns the team.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TOKEN_MISSING_ABILITY": {
                                        "summary": "TOKEN_MISSING_ABILITY",
                                        "value": {
                                            "error": {
                                                "code": "TOKEN_MISSING_ABILITY",
                                                "message": "The presented API token does not carry the ability required to perform this action.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                                "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "context": {
                                                    "required_ability": "project:view"
                                                }
                                            }
                                        }
                                    },
                                    "FORBIDDEN": {
                                        "summary": "FORBIDDEN",
                                        "value": {
                                            "error": {
                                                "code": "FORBIDDEN",
                                                "message": "The token holder can see this resource but may not change it.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                                "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "TEAM_TIER_REQUIRED": {
                                        "summary": "TEAM_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "TEAM_TIER_REQUIRED",
                                                "message": "This operation requires the creator's account to be on the Growth plan.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    },
                                    "CONNECTOR_TIER_REQUIRED": {
                                        "summary": "CONNECTOR_TIER_REQUIRED",
                                        "value": {
                                            "error": {
                                                "code": "CONNECTOR_TIER_REQUIRED",
                                                "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                                "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/IdempotencyKeyReused"
                    },
                    "425": {
                        "$ref": "#/components/responses/IdempotencyReplayInProgress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "webhook-endpoint:update"
                ],
                "x-mcp-tools": [
                    "resume_webhook_endpoint"
                ]
            }
        },
        "/v1/webhook-events": {
            "get": {
                "operationId": "v1.webhook-events.index",
                "description": "```bash\ncurl \"https://api.subscriby.net/v1/webhook-events?type=subscription.created&limit=3\" \\\n  -H \"Authorization: Bearer $SUBSCRIBY_TOKEN\"\n```\n\nThe most recent deliveries of one event type, newest first, as the envelopes the endpoints received. `limit` defaults to 3 and is capped at 10; `project_id` restricts to deliveries whose endpoint is scoped to that project.\n\n`api_version` is the payload-envelope stamp the dispatcher wrote at delivery time; see [versioning](https://docs.subscriby.net/api/v1/versioning-and-deprecation). Results are ordered by `created_at` descending. Only deliveries against endpoints owned by the token's team are returned; other tenants' events are never surfaced.\n\n`data` is empty when no endpoint in your team is subscribed to the requested event type yet, or when no delivery has fired for that type since the relevant endpoint was created. Zapier, Make, and n8n all fall back to the trigger's static sample in that case, so builders can still author a Zap end-to-end before the first live event flows.",
                "summary": "Poll recent webhook events",
                "tags": [
                    "Webhook Events"
                ],
                "parameters": [
                    {
                        "name": "type",
                        "in": "query",
                        "required": true,
                        "description": "The event name to sample, such as `subscription.created`; must be a case from the outbound webhook event catalog. An unknown name is refused.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.created"
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "How many recent deliveries to return, 1 to 10.",
                        "schema": {
                            "type": "integer",
                            "default": 3
                        }
                    },
                    {
                        "name": "project_id",
                        "in": "query",
                        "description": "Restrict to deliveries whose endpoint is confined to this project.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Array of `WebhookEventResource`",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The items.",
                                            "items": {
                                                "$ref": "#/components/schemas/WebhookEventResource"
                                            }
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                },
                                "examples": {
                                    "example-1": {
                                        "summary": "Example",
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "evt_01HXZ3Q8M7Y2K4N6P9R1T3V5W7",
                                                    "type": "subscription.created",
                                                    "created_at": "2026-05-18T10:05:00Z",
                                                    "api_version": "2026-05-01",
                                                    "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                    "data": {
                                                        "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                                        "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                        "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                                                    }
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "description": "`TENANT_MISMATCH`: with `reason: missing_team_scope` when the token carries no team scope.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "TENANT_MISMATCH": {
                                        "summary": "TENANT_MISMATCH",
                                        "value": {
                                            "error": {
                                                "code": "TENANT_MISMATCH",
                                                "message": "The requested resource does not belong to the team this API token is scoped to.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                                "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.\n\nOn this endpoint: `VALIDATION_FAILED`: when `type` is missing or not an event name from the catalog, `limit` is outside 1 to 10, or `project_id` is not a UUID.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                },
                                "examples": {
                                    "VALIDATION_FAILED": {
                                        "summary": "VALIDATION_FAILED",
                                        "value": {
                                            "error": {
                                                "code": "VALIDATION_FAILED",
                                                "message": "The request payload failed validation.",
                                                "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                                "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                                "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                                "fields": {
                                                    "name": [
                                                        "The name field is required."
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-required-scopes": [
                    "webhook-delivery:view-any"
                ]
            }
        }
    },
    "webhooks": {
        "project.created": {
            "post": {
                "operationId": "webhook.project.created",
                "description": "### When this fires\n\nA creator registers a new project. The event lands the moment the new project becomes available for further configuration.\n\nThe project `description` is **not** included in the snapshot. Fetch it with [the project endpoint](https://docs.subscriby.net/api/v1/reference/projects) if you need it.\n\n### Caveats\n\n- Use the `SB-Event-Id` header to dedupe deliveries; it carries the same ULID as `id`, without the `evt_` prefix.\n- `project.created` fires only for projects created through the REST API or MCP; projects created in the dashboard emit no `project.created`, so it is not guaranteed to be the first event you see for a `project_id`. Subsequent events on the same project may interleave.\n- Archived/restored states are a separate event pair: listen for `project.archived` and `project.restored` rather than relying on `data.project.active` flipping inside `project.updated`.\n\n### Related events\n\n- `project.updated`: fires on subsequent mutable-field changes.\n- `project.archived`: paired with `project.restored` for soft-disable transitions.",
                "summary": "A creator registers a new project.",
                "tags": [
                    "project.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "project.created"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `project.created` here.",
                                        "enum": [
                                            "project.created"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "project": {
                                                "type": "object",
                                                "description": "Snapshot of the new project: `id`, `name`, `handle`, `active`, `team_id` only.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Project identifier; matches the top-level `project_id`."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Display name shown in the dashboard and on the public landing page."
                                                    },
                                                    "handle": {
                                                        "type": "string",
                                                        "description": "URL slug for the public landing page."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Always `true` at creation; flips on archive / restore."
                                                    },
                                                    "team_id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Team that owns the project (a personal team for solo creators)."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "handle",
                                                    "active",
                                                    "team_id"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "project"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.created",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "project": {
                                                "id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "name": "Research Premium",
                                                "handle": "research-premium",
                                                "active": true,
                                                "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project:view"
                ],
                "x-webhook-family": "project"
            }
        },
        "project.updated": {
            "post": {
                "operationId": "webhook.project.updated",
                "description": "### When this fires\n\nAny mutable field on a project changes: display name, handle, description, terms, privacy text, or other dashboard-editable settings. State-flag transitions (archive, restore) emit dedicated events instead.\n\n### Caveats\n\n- The `changes` block contains only the fields that mutated; unchanged fields are not included.\n- `changes` can report fields the `project` snapshot does not carry: `description`, `terms`, `privacy`, `metrics`, `banner_url`, and `photo_url`. Read the new value from `changes[field].to`, or fetch the project from [the project endpoint](https://docs.subscriby.net/api/v1/reference/projects).\n- `POST /v1/projects/{project}/archive` and `/restore` emit the dedicated `project.archived` / `project.restored` events, but a plain `PATCH` that sets `active` reports the flip in `changes.active` on `project.updated` instead. Handle both.\n- Connecting or disconnecting an installation does not trigger `project.updated`; it emits `connector.connected` / `connector.disconnected`.\n\n### Related events\n\n- `project.created`: predecessor for any `project.updated` event.\n- `project.archived`, `project.restored`: dedicated state-transition events.",
                "summary": "Any mutable project field changes.",
                "tags": [
                    "project.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "project.updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `project.updated` here.",
                                        "enum": [
                                            "project.updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "project": {
                                                "type": "object",
                                                "description": "Post-update project snapshot: `id`, `name`, `handle`, `active`, `team_id` only.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Project identifier; matches the top-level `project_id`."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Display name after the change."
                                                    },
                                                    "handle": {
                                                        "type": "string",
                                                        "description": "URL slug for the public landing page after the change."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Active flag after the change."
                                                    },
                                                    "team_id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Team that owns the project."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "handle",
                                                    "active",
                                                    "team_id"
                                                ]
                                            },
                                            "changes": {
                                                "type": "object",
                                                "description": "Map of fields that changed. Keys are project attribute names; values are `from` / `to` pairs.",
                                                "additionalProperties": {
                                                    "type": "object",
                                                    "properties": {
                                                        "from": {
                                                            "description": "The attribute's previous value, after model casting."
                                                        },
                                                        "to": {
                                                            "description": "The attribute's new value, as validated."
                                                        }
                                                    },
                                                    "required": [
                                                        "from",
                                                        "to"
                                                    ]
                                                }
                                            }
                                        },
                                        "required": [
                                            "project",
                                            "changes"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.updated",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "project": {
                                                "id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "name": "Research Premium",
                                                "handle": "research-premium",
                                                "active": true,
                                                "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86"
                                            },
                                            "changes": {
                                                "description": {
                                                    "from": "Weekly research drops.",
                                                    "to": "Daily research drops and monthly AMAs."
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project:view"
                ],
                "x-webhook-family": "project"
            }
        },
        "project.archived": {
            "post": {
                "operationId": "webhook.project.archived",
                "description": "### When this fires\n\nA project is archived through `POST /v1/projects/{project}/archive` or the MCP `archive_project` tool. Archiving from the dashboard does not emit this event. The only state change is the project's `active` flag flipping to `false`; existing subscriptions and the public landing page are untouched.\n\n### Caveats\n\n- Archive is reversible; pair with `project.restored` for the inverse transition.\n- Subscribers retain their existing access until their `ends_at` ticks over. Expect `subscription.expired` events to follow as those subscriptions wind down.\n- Hard-delete fires `project.deleted` instead and is final.\n\n### Related events\n\n- `project.restored`: paired transition.\n- `project.deleted`: terminal state, replaces archive when the row is hard-deleted.",
                "summary": "Creator archives the project; access is suspended.",
                "tags": [
                    "project.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "project.archived"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `project.archived` here.",
                                        "enum": [
                                            "project.archived"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "project": {
                                                "type": "object",
                                                "description": "Snapshot of the archived project.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Project identifier; matches the top-level `project_id`."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Display name."
                                                    },
                                                    "handle": {
                                                        "type": "string",
                                                        "description": "URL slug for the public landing page."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Always `false` for this event."
                                                    },
                                                    "team_id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Team that owns the project (a personal team for solo creators)."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "handle",
                                                    "active",
                                                    "team_id"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "project"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.archived",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "project": {
                                                "id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "name": "Research Premium",
                                                "handle": "research-premium",
                                                "active": false,
                                                "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project:view"
                ],
                "x-webhook-family": "project"
            }
        },
        "project.restored": {
            "post": {
                "operationId": "webhook.project.restored",
                "description": "### When this fires\n\nA previously archived project is restored. The public landing page becomes reachable again, the `active` flag returns to `true`, and new subscriptions can be created.\n\n### Caveats\n\n- Existing churned subscribers do not auto-re-activate. They must redeem a new subscription, which triggers `subscription.created`.\n- Connector installations persist across archive / restore. No `connector.*` events fire on restore.\n\n### Related events\n\n- `project.archived`: paired transition.\n- `subscription.created`: emits when subscribers rejoin.",
                "summary": "An archived project is re-activated.",
                "tags": [
                    "project.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "project.restored"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `project.restored` here.",
                                        "enum": [
                                            "project.restored"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "project": {
                                                "type": "object",
                                                "description": "Snapshot of the restored project.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Project identifier; matches the top-level `project_id`."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Display name."
                                                    },
                                                    "handle": {
                                                        "type": "string",
                                                        "description": "URL slug for the public landing page."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Always `true` for this event."
                                                    },
                                                    "team_id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Team that owns the project (a personal team for solo creators)."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "handle",
                                                    "active",
                                                    "team_id"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "project"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.restored",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "project": {
                                                "id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "name": "Research Premium",
                                                "handle": "research-premium",
                                                "active": true,
                                                "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project:view"
                ],
                "x-webhook-family": "project"
            }
        },
        "project.deleted": {
            "post": {
                "operationId": "webhook.project.deleted",
                "description": "### When this fires\n\nA project is hard-deleted by the creator. The project row and dependent data are removed; this is the final event you will receive for that `project_id`.\n\n> This is the final event you will receive for the given `project_id`. Stop emitting requests against this project after delivery.\n\n### Caveats\n\n- After this event, the project's API endpoints will respond `404`. Treat the row as gone.\n- Dependent rows (plans, subscriptions, resources) cascade but do **not** fan out their own `*.deleted` events. Handle the project-level cleanup once.\n- Webhook subscriptions targeting only this project should be torn down on your side; the platform stops emitting events for it.\n\n### Related events\n\n- `project.archived`: typical predecessor.\n- `project.created`: first event in the lifecycle.",
                "summary": "Project hard-deleted. Final event from that project.",
                "tags": [
                    "project.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "project.deleted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `project.deleted` here.",
                                        "enum": [
                                            "project.deleted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "project": {
                                                "type": "object",
                                                "description": "Last-known snapshot of the project before deletion.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Project identifier; matches the top-level `project_id`."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Display name."
                                                    },
                                                    "handle": {
                                                        "type": "string",
                                                        "description": "URL slug for the public landing page."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Last-known active flag before deletion."
                                                    },
                                                    "team_id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Team that owns the project (a personal team for solo creators)."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "handle",
                                                    "active",
                                                    "team_id"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "project"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.deleted",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "project": {
                                                "id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "name": "Research Premium",
                                                "handle": "research-premium",
                                                "active": true,
                                                "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project:view"
                ],
                "x-webhook-family": "project"
            }
        },
        "project.design_published": {
            "post": {
                "operationId": "webhook.project.design_published",
                "description": "### When this fires\n\nA creator published the portal design's draft on the designer or the platform bot, or an integration did over `POST /v1/projects/{project}/portal-design/publish` or `publish_portal_design`. The portal, the plan embed and the social card paint with the new design on their next render. A draft saved and never published fires nothing.\n\nThe design itself does not travel. Read it with [the portal design endpoint](https://docs.subscriby.net/api/v1/reference/portal-design) when the keys matter.\n\n### Caveats\n\n- A publish from the dashboard and one from the API look the same; nothing in the payload says which surface published.\n- `sections` compares documents, so a key put back to its earlier value in the same draft leaves its section out.\n\n### Related events\n\n- `project.updated`: the project's own fields, never the design.",
                "summary": "A drafted portal design was published.",
                "tags": [
                    "project.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "project.design_published"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `project.design_published` here.",
                                        "enum": [
                                            "project.design_published"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "project": {
                                                "type": "object",
                                                "description": "Snapshot of the project: `id`, `name`, `handle`, `active`, `team_id` only."
                                            },
                                            "published_at": {
                                                "type": "string",
                                                "description": "When the design went live, ISO 8601."
                                            },
                                            "sections": {
                                                "type": "array",
                                                "description": "The sections whose keys differ from the design published before, in the designer's order: `brand`, `colours`, `typography`, `shape`, `layout`, `copy`, `blocks`, `extras`, `announcement`, `media`, `sections`, `behaviour`, `visibility`, `language`. Empty when the draft matched what was already published.",
                                                "items": {
                                                    "type": "string"
                                                }
                                            }
                                        },
                                        "required": [
                                            "project",
                                            "published_at",
                                            "sections"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.design_published",
                                        "created_at": "2026-10-26T16:40:08Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "project": {
                                                "id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                                "name": "Research Premium",
                                                "handle": "research-premium",
                                                "active": true,
                                                "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86"
                                            },
                                            "published_at": "2026-10-26T16:40:08+00:00",
                                            "sections": [
                                                "colours",
                                                "typography"
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project:view"
                ],
                "x-webhook-family": "project"
            }
        },
        "project.resource.created": {
            "post": {
                "operationId": "webhook.project.resource.created",
                "description": "### When this fires\n\nA creator registers a manual perk on the project, from the dashboard's resource editor, `POST /v1/projects/{project}/resources` or the `create_resource` tool. A place a connector gates never arrives here: the connector links it and announces `project.resource.linked` instead.\n\nThe resource `description` is **not** included in the payload. Fetch it with [the resource endpoint](https://docs.subscriby.net/api/v1/reference/resources) if you need it.\n\n### Caveats\n\n- `project.resource.linked` is not a follow-up to this event; it creates its own resource row and carries a different `resource_id`.\n- A manual perk is bound to no place and is not linkable; it appears once on creation and once on deletion.\n\n### Related events\n\n- `project.resource.linked`: a place a connector gates becomes a resource.\n- `project.resource.deleted`: terminal state for a resource.",
                "summary": "A manual perk is registered under a project.",
                "tags": [
                    "project.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "project.resource.created"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `project.resource.created` here.",
                                        "enum": [
                                            "project.resource.created"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "resource": {
                                                "type": "object",
                                                "description": "The new resource: `id`, `title`, `kind`, `connector`, `space`, `active` only.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Resource identifier."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Display title."
                                                    },
                                                    "kind": {
                                                        "type": "string",
                                                        "description": "Always `manual` on this event. A connector's kind (`telegram:channel`) appears via `project.resource.linked`."
                                                    },
                                                    "connector": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Always `null` here: a manual perk lives on no connector."
                                                    },
                                                    "space": {
                                                        "type": [
                                                            "object",
                                                            "null"
                                                        ],
                                                        "description": "Always `null` here: a manual perk is bound to no place."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Active flag at creation time."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "title",
                                                    "kind",
                                                    "connector",
                                                    "space",
                                                    "active"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "resource"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.resource.created",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "resource": {
                                                "id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                "title": "Welcome packet",
                                                "kind": "manual",
                                                "connector": null,
                                                "space": null,
                                                "active": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-resource:view"
                ],
                "x-webhook-family": "project"
            }
        },
        "project.resource.linked": {
            "post": {
                "operationId": "webhook.project.resource.linked",
                "description": "### When this fires\n\nA creator links a place from a connector: a channel, group or supergroup from the bot's picker, or any connector's own picker answering a [link request](https://docs.subscriby.net/api/v1/reference/resources). The connector writes the resource row and this event announces it. This **creates** the resource row; no `project.resource.created` precedes it.\n\n### Caveats\n\n- Re-linking a place after an unlink creates a **new** resource row. The `project.resource.linked` you receive carries a different `resource_id` than the earlier `project.resource.unlinked`, and the unlinked row remains behind with `space: null`.\n- Linking the same place to the same project twice announces nothing the second time: the connector's write is idempotent and answers the existing resource.\n- A manual perk cannot be linked; it has no underlying place, so its `kind` is `manual` and it arrives through `project.resource.created`.\n\n### Related events\n\n- `project.resource.unlinked`: paired transition.\n- `project.resource.created`: the separate REST / MCP path for manual perks; not a predecessor of this event.",
                "summary": "A place a creator picked on a connector becomes a resource of a project.",
                "tags": [
                    "project.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "project.resource.linked"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `project.resource.linked` here.",
                                        "enum": [
                                            "project.resource.linked"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors top-level `project_id`."
                                            },
                                            "resource_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Resource identifier."
                                            },
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector key the place is on (`telegram`, and each connector the marketplace lists as it launches)."
                                            },
                                            "kind": {
                                                "type": "string",
                                                "description": "The resource's kind, `connector:kind` (`telegram:channel`, `telegram:group`, `telegram:supergroup`, a future connector's own kinds)."
                                            },
                                            "space_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The space the resource gates, as [the resource endpoint](https://docs.subscriby.net/api/v1/reference/resources) returns it under `space.id`. Null only for a place whose installation the core has no row for yet."
                                            },
                                            "title": {
                                                "type": "string",
                                                "description": "The place's title at link time."
                                            }
                                        },
                                        "required": [
                                            "project_id",
                                            "resource_id",
                                            "connector",
                                            "kind",
                                            "space_id",
                                            "title"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.resource.linked",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "connector": "telegram",
                                            "kind": "telegram:channel",
                                            "space_id": "3c1f7a58-2b6e-4d90-8f41-6a2e9c5d7b10",
                                            "title": "Research Premium Lounge"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-resource:view"
                ],
                "x-webhook-family": "project"
            }
        },
        "project.resource.unlinked": {
            "post": {
                "operationId": "webhook.project.resource.unlinked",
                "description": "### When this fires\n\nA previously linked place is unbound from the resource by the creator, through the REST API or MCP.\n\n### Caveats\n\n- The resource row is preserved; only the place binding is removed. To delete it entirely, see `project.resource.deleted`.\n- Active subscribers may receive `member.resource_removed` as access is revoked.\n\n### Related events\n\n- `project.resource.linked`: paired transition.\n- `project.resource.deleted`: terminal state.",
                "summary": "Resource disconnected from a project.",
                "tags": [
                    "project.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "project.resource.unlinked"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `project.resource.unlinked` here.",
                                        "enum": [
                                            "project.resource.unlinked"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "resource": {
                                                "type": "object",
                                                "description": "The resource after unlinking. The row still exists.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Resource that was unlinked."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Resource title."
                                                    },
                                                    "kind": {
                                                        "type": "string",
                                                        "description": "The connector's kind spelled `connector:kind` (`telegram:channel`); a resource keeps its kind when its place is removed."
                                                    },
                                                    "connector": {
                                                        "type": "string",
                                                        "description": "The connector the place was on."
                                                    },
                                                    "space": {
                                                        "type": [
                                                            "object",
                                                            "null"
                                                        ],
                                                        "description": "Always `null` on this event: the place binding is what was removed."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Active flag, unchanged by unlinking."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "title",
                                                    "kind",
                                                    "connector",
                                                    "space",
                                                    "active"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "resource"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.resource.unlinked",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "resource": {
                                                "id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                "title": "Sunday Slate Channel",
                                                "kind": "telegram:channel",
                                                "connector": "telegram",
                                                "space": null,
                                                "active": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-resource:view"
                ],
                "x-webhook-family": "project"
            }
        },
        "project.resource.deleted": {
            "post": {
                "operationId": "webhook.project.resource.deleted",
                "description": "### When this fires\n\nA resource is soft-deleted by the creator through the REST API or MCP. Existing subscriber access to the underlying place is not revoked by this action and no `member.resource_removed` events follow from it.\n\n> This is the final event you will receive for the given `resource_id`. The row is retained with `deleted_at` stamped and disappears from the API.\n\n### Caveats\n\n- After this event, API endpoints scoped to the resource respond `404`.\n\n### Related events\n\n- `project.resource.unlinked`: typical predecessor.",
                "summary": "Resource soft-deleted from a project.",
                "tags": [
                    "project.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "project.resource.deleted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `project.resource.deleted` here.",
                                        "enum": [
                                            "project.resource.deleted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "resource": {
                                                "type": "object",
                                                "description": "Snapshot of the resource as it was immediately before deletion.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Resource that was soft-deleted."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Last-known title."
                                                    },
                                                    "kind": {
                                                        "type": "string",
                                                        "description": "`manual`, or the connector's kind spelled `connector:kind` (`telegram:channel`)."
                                                    },
                                                    "connector": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "The connector the place was on; `null` for a manual perk."
                                                    },
                                                    "space": {
                                                        "type": [
                                                            "object",
                                                            "null"
                                                        ],
                                                        "description": "The place it was bound to (`id`, `external_id`, `title`); `null` for a manual perk and for an unlinked row.",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "format": "uuid",
                                                                "description": "Subscriby's id for the place."
                                                            },
                                                            "external_id": {
                                                                "type": "string",
                                                                "description": "The platform's own id for the place."
                                                            },
                                                            "title": {
                                                                "type": "string",
                                                                "description": "The place's title as the platform reported it."
                                                            }
                                                        }
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Last-known active flag."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "title",
                                                    "kind",
                                                    "connector",
                                                    "space",
                                                    "active"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "resource"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.resource.deleted",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "resource": {
                                                "id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                "title": "Sunday Slate Channel",
                                                "kind": "telegram:channel",
                                                "connector": "telegram",
                                                "space": {
                                                    "id": "3c1f7a58-2b6e-4d90-8f41-6a2e9c5d7b10",
                                                    "external_id": "-1001234567890",
                                                    "title": "Sunday Slate Channel"
                                                },
                                                "active": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-resource:view"
                ],
                "x-webhook-family": "project"
            }
        },
        "project.resource.updated": {
            "post": {
                "operationId": "webhook.project.resource.updated",
                "description": "### When this fires\n\nA creator changes one of the three editable fields on a resource (`title`, `description` or `active`) and at least one of them is actually different afterwards. Every surface that can make that change raises it:\n\n- **Dashboard**: the resource editor on the project's Resources page, and the on/off switch on each resource row.\n- **REST**: `PATCH /v1/projects/{project}/resources/{resource}` for title and description edits, and `POST /v1/projects/{project}/resources/{resource}/activate` / `deactivate` for the switch.\n- **MCP**: the `update_resource`, `activate_resource` and `deactivate_resource` tools.\n\nIt **also** fires when the place behind a resource is **swapped**: a [Disaster Recovery](https://docs.subscriby.net/connectors/telegram/replacing-channels-and-groups) replacement, an automatic failover to a standby, **Swap & Grant Resource** from the resources list, or the undo of any of those. That event carries `changes.space_id` with the previous and the new space, `changes.kind` when the platform upgraded the place in the same move (a group that became a supergroup), and `resource.space` already reads the new place.\n\nIt does **not** fire when:\n\n- Nothing changed. A `PATCH` that re-sends the stored values, or an `activate` call on a resource that is already active, writes nothing and emits nothing.\n- The place is linked for the first time or removed. That is the connector's link (`project.resource.linked`) or an unlink (`project.resource.unlinked`).\n- The resource is deleted. That is `project.resource.deleted`, and no `updated` event precedes it.\n\n> There are no `project.resource.activated` / `deactivated` events. Switching a resource on or off arrives here, as `changes.active`, alongside title and description edits. One save is one event, and it lists only what changed.\n\n### Caveats\n\n- The `description` is not in the `resource` snapshot, matching every other `project.resource.*` event, but when the description is what changed, `changes.description.to` carries the new text in full. Read it from there rather than following up with a request to the resource endpoint.\n- Switching a resource off does not touch the plans that sell it. The connector stops granting that one place while the plans keep selling everything else, so a `changes.active` flip to `false` is \"this perk is paused\", not \"this plan changed\". No `plan.updated` follows.\n- An `activate` / `deactivate` call and a `PATCH` that sets `active` produce the same event with the same `changes.active` shape. The payload does not say which route was used.\n- A swap that also switches an inactive resource back on carries `changes.active` beside `changes.space_id`, because the swap reactivates what it repairs.\n- `changes` contains only the fields that mutated. A `PATCH` carrying all three fields where only one differs reports one key.\n\n### Related events\n\n- `project.resource.created`: the manual perk this event later edits.\n- `project.resource.linked` / `project.resource.unlinked`: the place bound for the first time or removed, which this event never reports.\n- `project.resource.deleted`: terminal state for a resource.\n- `project.resource.status_changed`: the health transition that usually precedes a recovery swap.\n- `recovery.resource_replaced` / `recovery.resource_failed_over`: the recovery ledger's own word for the same swap.",
                "summary": "A resource's title, description or on/off switch changes, or a recovery moves it onto another place.",
                "tags": [
                    "project.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "project.resource.updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `project.resource.updated` here.",
                                        "enum": [
                                            "project.resource.updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "resource": {
                                                "type": "object",
                                                "description": "Post-update snapshot: `id`, `title`, `kind`, `connector`, `space`, `active` only.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Resource identifier."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Display title after the change."
                                                    },
                                                    "kind": {
                                                        "type": "string",
                                                        "description": "`manual`, or the connector's kind spelled `connector:kind`. Shown so a consumer can branch without a lookup; changes only when a swap upgraded the place, and then `changes.kind` says so."
                                                    },
                                                    "connector": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "The connector the place is on; `null` for a manual perk."
                                                    },
                                                    "space": {
                                                        "type": [
                                                            "object",
                                                            "null"
                                                        ],
                                                        "description": "The place after the change: `id`, the platform's `external_id`, `title`. `null` for a manual perk and for an unlinked row.",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "format": "uuid",
                                                                "description": "Subscriby's id for the place; `changes.space_id.to` reads the same value after a swap."
                                                            },
                                                            "external_id": {
                                                                "type": "string",
                                                                "description": "The platform's own id for the place."
                                                            },
                                                            "title": {
                                                                "type": "string",
                                                                "description": "The place's title as the platform reported it."
                                                            }
                                                        }
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Switch position after the change."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "title",
                                                    "kind",
                                                    "connector",
                                                    "space",
                                                    "active"
                                                ]
                                            },
                                            "changes": {
                                                "type": "object",
                                                "description": "The fields that changed. Keys are one or more of `title`, `description`, `active`, `space_id`, `kind`; values are before/after pairs. Never empty: an empty map means no event.",
                                                "properties": {
                                                    "title": {
                                                        "type": "object",
                                                        "description": "Present only when the title changed.",
                                                        "properties": {
                                                            "from": {
                                                                "type": "string",
                                                                "description": "Previous title."
                                                            },
                                                            "to": {
                                                                "type": "string",
                                                                "description": "New title."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    },
                                                    "description": {
                                                        "type": "object",
                                                        "description": "Present only when the description changed.",
                                                        "properties": {
                                                            "from": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "Previous description. `null` when there was none."
                                                            },
                                                            "to": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "New description, up to 1000 characters of well-formed HTML, or `null` when it was cleared."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    },
                                                    "active": {
                                                        "type": "object",
                                                        "description": "Present only when the switch flipped.",
                                                        "properties": {
                                                            "from": {
                                                                "type": "boolean",
                                                                "description": "Previous switch position."
                                                            },
                                                            "to": {
                                                                "type": "boolean",
                                                                "description": "New switch position."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    },
                                                    "space_id": {
                                                        "type": "object",
                                                        "description": "Present only when a recovery, a failover, a manual swap or an undo moved the place.",
                                                        "properties": {
                                                            "from": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "format": "uuid",
                                                                "description": "The space the resource pointed at before the swap."
                                                            },
                                                            "to": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "format": "uuid",
                                                                "description": "The space it points at now; `resource.space.id` reads the same value."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    },
                                                    "kind": {
                                                        "type": "object",
                                                        "description": "Present only when a swap upgraded the place.",
                                                        "properties": {
                                                            "from": {
                                                                "type": "string",
                                                                "description": "The kind before the swap."
                                                            },
                                                            "to": {
                                                                "type": "string",
                                                                "description": "The kind after it (`telegram:supergroup` for a group the platform converted)."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    }
                                                }
                                            }
                                        },
                                        "required": [
                                            "resource",
                                            "changes"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.resource.updated",
                                        "created_at": "2026-09-06T09:14:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "resource": {
                                                "id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                "title": "Members lounge (VIP)",
                                                "kind": "telegram:supergroup",
                                                "connector": "telegram",
                                                "space": {
                                                    "id": "3c1f7a58-2b6e-4d90-8f41-6a2e9c5d7b10",
                                                    "external_id": "-1001234567890",
                                                    "title": "Members lounge"
                                                },
                                                "active": true
                                            },
                                            "changes": {
                                                "title": {
                                                    "from": "Members lounge",
                                                    "to": "Members lounge (VIP)"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-resource:view"
                ],
                "x-webhook-family": "project"
            }
        },
        "project.resource.status_changed": {
            "post": {
                "operationId": "webhook.project.resource.status_changed",
                "description": "### When this fires\n\nA channel or group linked to a project transitions into or out of a degraded state. The degraded reasons are:\n\n| `reason`                | What the platform told us                                                             | Recovery                                                    |\n| ----------------------- | ------------------------------------------------------------------------------------- | ----------------------------------------------------------- |\n| `chat_not_found`        | The chat no longer exists: deleted, or banned by the platform.                        | Replace the chat (a channel recovery).                      |\n| `bot_removed`           | Our bot was removed from the chat, so it can no longer admit or remove members.       | Re-add the bot as an administrator, or replace the chat.    |\n| `bot_not_administrator` | The bot is still in the chat but lost its administrator role.                         | Promote it again with the invite and restrict rights.       |\n| `bot_missing_rights`    | The bot is an administrator without the *invite users* or *restrict members* right.   | Grant both rights again.                                    |\n| `connector_api_error`   | The platform refused the probe for a reason we could not classify.                    | Re-check; replace the chat if it persists.                  |\n\nThe `healthy` event carries `reason: null` and fires when a probe finds the resource answering again, or when a recovery re-points it at a new chat.\n\nA `chat_not_found` or `bot_removed` transition also opens a **recovery incident** on the creator's [Disaster Recovery](https://docs.subscriby.net/disaster-recovery) page, alerts them by email and on their connected account, and, on Growth, with automatic failover switched on, swaps the resource for its standby without anyone signed in.\n\nIt does **not** fire when:\n\n- A probe finds the same state as last time. Only transitions are announced.\n- A probe cannot reach the platform at all. A transport failure keeps the previous state.\n- The resource is a manual perk. Only channels and groups are probed.\n\n> Fires on a **transition**, not on a schedule. Subscriby probes every linked channel and group hourly, every five minutes while a pass window is open or imminent, and immediately when real work fails (an invite link cannot be minted, a join request cannot be approved). You get one event when the resource breaks and one when it recovers, never an event per probe.\n\n### Related events\n\n- `connector.status_changed`: the same idea for the project's installation.\n- `project.resource.updated`: fires with `changes.space_id` when a recovery re-points the resource at a replacement place.",
                "summary": "A channel or group enters or exits a degraded state: banned, deleted, or the bot lost its rights.",
                "tags": [
                    "project.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "project.resource.status_changed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `project.resource.status_changed` here.",
                                        "enum": [
                                            "project.resource.status_changed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Same project, repeated for consumers that read `data` alone."
                                            },
                                            "resource_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The channel or group whose health changed."
                                            },
                                            "status": {
                                                "type": "string",
                                                "description": "The state after the transition.",
                                                "enum": [
                                                    "healthy",
                                                    "degraded"
                                                ]
                                            },
                                            "reason": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Why it is degraded. `null` on a `healthy` transition.",
                                                "enum": [
                                                    "chat_not_found",
                                                    "bot_removed",
                                                    "bot_not_administrator",
                                                    "bot_missing_rights",
                                                    "connector_api_error",
                                                    null
                                                ]
                                            }
                                        },
                                        "required": [
                                            "project_id",
                                            "resource_id",
                                            "status",
                                            "reason"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.resource.status_changed",
                                        "created_at": "2026-09-07T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "status": "degraded",
                                            "reason": "chat_not_found"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-resource:view"
                ],
                "x-webhook-family": "project"
            }
        },
        "project.payment_method.updated": {
            "post": {
                "operationId": "webhook.project.payment_method.updated",
                "description": "### When this fires\n\nA payment method on the project changes and at least one of `active`, `linked` or a key inside its stored `config` is different afterwards. The surfaces that raise it:\n\n- **Dashboard**: the payment method editor on the project's Payment Methods page (credentials and switches), and the on/off toggle on each gateway row.\n- **Bot**: the main bot's payment-method wizard, when a creator walks through connecting a gateway that the project already has in that mode. The wizard re-saves the row through the same path as the dashboard.\n- **REST**: `POST /v1/projects/{project}/payment-methods/{method}/activate` and `/deactivate`. There is no `PATCH` for payment methods, so credentials cannot be rotated over REST.\n- **MCP**: the `activate_payment_method` and `deactivate_payment_method` tools.\n\nIt does **not** fire when:\n\n- Nothing changed. Activating a gateway that is already on, or re-saving identical credentials, writes nothing and emits nothing.\n- A Stripe method is switched on before its Connect account is attached. The call is refused, the row is untouched and there is no event.\n- Stripe Connect onboarding completes or is disconnected. Those flows write the row directly and raise no event, even though they change `linked` and `active`.\n- A gateway is first set up. There is no `project.payment_method.created` event; the first thing you hear about a new gateway is its first update or its deletion.\n- The gateway is removed. That is `project.payment_method.deleted`.\n\n> This payload never carries a credential. When gateway keys are rotated, `changes.config.keys` names **which** keys changed (`[\"clientId\"]`, `[\"secret\"]`) and nothing else. Neither the old nor the new value is sent, and the `payment_method` snapshot has no `config` at all.\n\n### Caveats\n\n- `linked` can appear in `changes` but is not in the snapshot. Read the new value from `changes.linked.to`, or from [the payment method endpoint](https://docs.subscriby.net/api/v1/reference/payment-methods), which does carry `linked`.\n- `mode` never appears in `changes`. A row's mode is fixed (live and test are separate rows), so switching a gateway from test to live is a different method with a different `id`, not an update to this one.\n- Every update re-queues a sync of the project's plans to that gateway, so a `plan.sync_completed` per active plan usually follows within a minute. Rotated credentials may point at a different gateway account whose catalogue has never seen the plans.\n- `config.keys` are the gateway's own field names as Subscriby stores them (`clientId`, `secret`, `publicKey`, …), not a normalised list. Stored config is merged on save, so a key is reported when its value changed or was added; keys are never removed through an update.\n- Switching a gateway off does not affect subscriptions already sold through it; they keep renewing. It only stops new buyers being offered that gateway.\n\n### Related events\n\n- `project.payment_method.deleted`: the gateway is removed from the project.\n- `plan.sync_completed`: the catalogue re-push that follows each update.",
                "summary": "A payment gateway's credentials, link state or on/off switch changes.",
                "tags": [
                    "project.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "project.payment_method.updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `project.payment_method.updated` here.",
                                        "enum": [
                                            "project.payment_method.updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "payment_method": {
                                                "type": "object",
                                                "description": "Post-update snapshot: `id`, `provider`, `mode`, `active` only. Never `config`, never `linked`.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Payment method identifier."
                                                    },
                                                    "provider": {
                                                        "type": "string",
                                                        "description": "A gateway slug (`stripe`, `paypal`, `skrill`, `coinpayments`, `paystack`, `razorpay`, `ceypay`, `accesscode`) or a `connector:provider` key for a currency a connector brings (`telegram:stars`); `platformcurrency` is the legacy alias earlier native rows carried."
                                                    },
                                                    "mode": {
                                                        "type": "string",
                                                        "description": "Which of the gateway's environments this row holds. A project has at most one row per provider per mode.",
                                                        "enum": [
                                                            "live",
                                                            "test"
                                                        ]
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Whether the gateway is offered to new buyers after the change."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "provider",
                                                    "mode",
                                                    "active"
                                                ]
                                            },
                                            "changes": {
                                                "type": "object",
                                                "description": "What changed. One or more of `active`, `linked`, `config`. Never empty: an empty map means no event.",
                                                "properties": {
                                                    "active": {
                                                        "type": "object",
                                                        "description": "Present only when the switch flipped.",
                                                        "properties": {
                                                            "from": {
                                                                "type": "boolean",
                                                                "description": "Previous switch position."
                                                            },
                                                            "to": {
                                                                "type": "boolean",
                                                                "description": "New switch position."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    },
                                                    "linked": {
                                                        "type": "object",
                                                        "description": "Present only when the link state changed.",
                                                        "properties": {
                                                            "from": {
                                                                "type": "boolean",
                                                                "description": "Previous link state."
                                                            },
                                                            "to": {
                                                                "type": "boolean",
                                                                "description": "New link state."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    },
                                                    "config": {
                                                        "type": "object",
                                                        "description": "Present only when at least one stored credential key changed.",
                                                        "properties": {
                                                            "keys": {
                                                                "type": "array",
                                                                "description": "The gateway credential keys whose value changed or was newly stored, e.g. `[\"clientId\", \"secret\"]`. Values are never sent.",
                                                                "items": {
                                                                    "type": "string"
                                                                }
                                                            }
                                                        },
                                                        "required": [
                                                            "keys"
                                                        ]
                                                    }
                                                }
                                            }
                                        },
                                        "required": [
                                            "payment_method",
                                            "changes"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.payment_method.updated",
                                        "created_at": "2026-09-06T09:20:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "payment_method": {
                                                "id": "a15d70c8-3e46-4b92-b70f-58c9d2140e63",
                                                "provider": "paypal",
                                                "mode": "live",
                                                "active": true
                                            },
                                            "changes": {
                                                "config": {
                                                    "keys": [
                                                        "clientId"
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                },
                                "payload-switch-flip": {
                                    "summary": "switch flip",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.payment_method.updated",
                                        "created_at": "2026-09-06T09:21:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "payment_method": {
                                                "id": "a15d70c8-3e46-4b92-b70f-58c9d2140e63",
                                                "provider": "paypal",
                                                "mode": "live",
                                                "active": false
                                            },
                                            "changes": {
                                                "active": {
                                                    "from": true,
                                                    "to": false
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-payment-method:view"
                ],
                "x-webhook-family": "project"
            }
        },
        "project.payment_method.deleted": {
            "post": {
                "operationId": "webhook.project.payment_method.deleted",
                "description": "### When this fires\n\nA creator removes a payment method from the project:\n\n- **Dashboard**: the remove action on the project's Payment Methods page.\n- **Bot**: the main bot's payment-method menu, \"disconnect\" on a connected gateway.\n- **REST**: `DELETE /v1/projects/{project}/payment-methods/{method}`.\n- **MCP**: the `delete_payment_method` tool.\n\nIt does **not** fire when:\n\n- A gateway is switched off. That is `project.payment_method.updated` with `changes.active`, and the row stays.\n- A Stripe method is disconnected from its Connect account. The row is kept (unlinked and inactive) and that flow raises no event at all.\n- The row was already gone. Deleting twice writes nothing the second time and emits nothing.\n\n> The row is soft-deleted, not destroyed. Subscriptions sold through the gateway keep pointing at it for refunds and history, and if the creator sets the same gateway up again in the same mode, the **same row is revived**. Expect this `id` to come back to life, and remember there is no `project.payment_method.created` event to tell you when it does.\n\n### Caveats\n\n- `active: true` here means the creator removed a gateway that was live for new purchases. If you mirror the project's checkout options anywhere, this is the event to react to; a deactivation would have arrived as `updated` first.\n- Existing subscriptions are untouched. Their renewals, refunds and history keep referencing this gateway even though the row no longer appears in the project's payment methods list.\n- `linked` is not in the snapshot, and nothing about the gateway's credentials or connected account is ever sent.\n\n### Related events\n\n- `project.payment_method.updated`: every change to the gateway before this one, including switching it off.\n- `project.deleted`: a project going away takes its gateways with it without a per-gateway event.",
                "summary": "A payment gateway is removed from a project.",
                "tags": [
                    "project.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "project.payment_method.deleted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `project.payment_method.deleted` here.",
                                        "enum": [
                                            "project.payment_method.deleted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "payment_method": {
                                                "type": "object",
                                                "description": "Snapshot taken immediately before the delete: `id`, `provider`, `mode`, `active` only. Never `config`.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Payment method identifier. No longer resolvable over the API once this event has fired."
                                                    },
                                                    "provider": {
                                                        "type": "string",
                                                        "description": "A gateway slug (`stripe`, `paypal`, `skrill`, `coinpayments`, `paystack`, `razorpay`, `ceypay`, `accesscode`) or a `connector:provider` key for a currency a connector brings (`telegram:stars`); `platformcurrency` is the legacy alias earlier native rows carried."
                                                    },
                                                    "mode": {
                                                        "type": "string",
                                                        "description": "Which of the gateway's environments the removed row held.",
                                                        "enum": [
                                                            "live",
                                                            "test"
                                                        ]
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Whether the gateway was still being offered to buyers at the moment it was removed."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "provider",
                                                    "mode",
                                                    "active"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "payment_method"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "project.payment_method.deleted",
                                        "created_at": "2026-09-06T09:25:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "payment_method": {
                                                "id": "a15d70c8-3e46-4b92-b70f-58c9d2140e63",
                                                "provider": "paypal",
                                                "mode": "live",
                                                "active": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-payment-method:view"
                ],
                "x-webhook-family": "project"
            }
        },
        "plan.created": {
            "post": {
                "operationId": "webhook.plan.created",
                "description": "### When this fires\n\nA plan is created through the REST API (`POST /v1/projects/{project}/plans`) or the `create_plan` MCP tool, or a finished pass season is duplicated into its next season. Plans created from the creator dashboard or the bot do not emit this event. The plan is immediately eligible for purchase if it was created in the active state.\n\n> **The two shapes are disjoint.** The API and MCP path sends `data.plan` and nothing else; the season-duplication path sends the four flat keys and no `data.plan` object. Branch on whether `data.plan` or `data.plan_id` is present before reading any other field.\n\n`billing_cycle` is only the unit. The multiplier lives in `billing_cycle_count` on the plan record and is **not** included in this payload: a \"3 month\" plan sends `billing_cycle: \"month\"` with no indication of the `3`. Nor is `trial_days`. Fetch the plan with `GET /v1/projects/{project}/plans/{plan}` when you need the full cadence or trial configuration.\n\n### Caveats\n\n- A `plan.created` event does not imply the plan has been synced to a payment-provider catalog. Listen for `plan.sync_completed` for that.\n- Trial is configured at create time. A later trial-only edit is only applied, and only then fires `plan.updated`, when the PATCH also carries a `kind` key; without it the trial fields are dropped and no event is emitted.\n\n### Related events\n\n- `plan.updated`: subsequent edits.\n- `plan.sync_completed`: provider catalog sync.",
                "summary": "A plan is first created on a project.",
                "tags": [
                    "plan.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "plan.created"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `plan.created` here.",
                                        "enum": [
                                            "plan.created"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan": {
                                                "type": "object",
                                                "description": "Sent by the API and MCP path only; absent when a season is duplicated.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Plan identifier."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Display name."
                                                    },
                                                    "price": {
                                                        "type": "string",
                                                        "format": "decimal",
                                                        "description": "Decimal amount as a string, e.g. `\"29.00\"`."
                                                    },
                                                    "currency_id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Currency row id, **not** an ISO 4217 code."
                                                    },
                                                    "billing_cycle": {
                                                        "type": "string",
                                                        "description": "Billing cadence unit.",
                                                        "enum": [
                                                            "day",
                                                            "week",
                                                            "month",
                                                            "year",
                                                            "lifetime"
                                                        ]
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "`true` if the plan is purchasable."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "price",
                                                    "currency_id",
                                                    "billing_cycle",
                                                    "active"
                                                ]
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Season-duplication payload only. Plan id of the new season."
                                            },
                                            "plan_name": {
                                                "type": "string",
                                                "description": "Season-duplication payload only. Display name of the new season's plan."
                                            },
                                            "kind": {
                                                "type": "string",
                                                "description": "Season-duplication payload only. Always `pass_series` on this path, since it clones a series.",
                                                "enum": [
                                                    "subscription",
                                                    "pass",
                                                    "pass_series"
                                                ]
                                            },
                                            "duplicated_from_plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Season-duplication payload only. The plan the season was cloned from."
                                            }
                                        }
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "plan.created",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan": {
                                                "id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "name": "Premium Monthly",
                                                "price": "29.00",
                                                "currency_id": "8f27a0d4-63be-4915-8c07-1a5d9e34b628",
                                                "billing_cycle": "month",
                                                "active": true
                                            }
                                        }
                                    }
                                },
                                "payload-season-duplication": {
                                    "summary": "season duplication",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "plan.created",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan_id": "b1a7c3d5-2e48-4f60-9a1b-7c5d3e820f94",
                                            "plan_name": "Season 4",
                                            "kind": "pass_series",
                                            "duplicated_from_plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "plan"
            }
        },
        "plan.updated": {
            "post": {
                "operationId": "webhook.plan.updated",
                "description": "### When this fires\n\nA plan is edited through the REST API (`PATCH /v1/projects/{project}/plans/{plan}`): pricing, name, currency, billing cadence, eligibility filters. Edits made in the creator dashboard do not emit this event, and trial fields are only written (and only then reported) when the payload also carries `kind`. An `active` flag sent on a PATCH is reported here as an ordinary `changes.active` entry. The dedicated `plan.activated` and `plan.deactivated` events come only from the publish and unpublish endpoints.\n\n### Caveats\n\n- Existing subscriptions priced on the old terms are not retroactively re-priced. New checkouts use the new price; renewals follow the billing rules.\n- An `active` flag sent on a PATCH is reported here as an ordinary `changes.active` entry. The dedicated `plan.activated` and `plan.deactivated` events come only from the publish and unpublish endpoints.\n\n### Related events\n\n- `plan.activated`, `plan.deactivated`: dedicated active-flag events.\n- `plan.sync_completed`: fires after price changes propagate to the provider catalog.",
                "summary": "Any mutable plan field changes.",
                "tags": [
                    "plan.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "plan.updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `plan.updated` here.",
                                        "enum": [
                                            "plan.updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan": {
                                                "type": "object",
                                                "description": "Full post-update plan snapshot, the same shape as `plan.created`.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Plan identifier."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Display name."
                                                    },
                                                    "price": {
                                                        "type": "string",
                                                        "format": "decimal",
                                                        "description": "Decimal amount as a string, e.g. `\"29.00\"`."
                                                    },
                                                    "currency_id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Currency row id, **not** an ISO 4217 code."
                                                    },
                                                    "billing_cycle": {
                                                        "type": "string",
                                                        "description": "Billing cadence unit.",
                                                        "enum": [
                                                            "day",
                                                            "week",
                                                            "month",
                                                            "year",
                                                            "lifetime"
                                                        ]
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Whether the plan is purchasable after the change."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "price",
                                                    "currency_id",
                                                    "billing_cycle",
                                                    "active"
                                                ]
                                            },
                                            "changes": {
                                                "type": "object",
                                                "description": "The fields that changed, each a `{from, to}` pair keyed by the plan attribute. `from` is the plan's previous value after model casting (price is a string, enum columns are their backed string value); `to` is the caller-supplied value as validated.",
                                                "additionalProperties": {
                                                    "type": "object"
                                                }
                                            }
                                        },
                                        "required": [
                                            "plan",
                                            "changes"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "plan.updated",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan": {
                                                "id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "name": "Premium Monthly",
                                                "price": "29.00",
                                                "currency_id": "8f27a0d4-63be-4915-8c07-1a5d9e34b628",
                                                "billing_cycle": "month",
                                                "active": true
                                            },
                                            "changes": {
                                                "price": {
                                                    "from": "25.0000",
                                                    "to": "29.00"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "plan"
            }
        },
        "plan.activated": {
            "post": {
                "operationId": "webhook.plan.activated",
                "description": "### When this fires\n\nAn inactive plan is flipped to active through the REST API (`POST /v1/projects/{project}/plans/{plan}/publish`) or the `publish_plan` MCP tool, and becomes purchasable on the project landing page. Toggling a plan on from the creator dashboard does not emit this event.\n\n### Caveats\n\n- Publishing a plan that is already active is a no-op: nothing is written and no event is emitted.\n- Activation does not retroactively touch existing subscriptions on the plan; only checkout availability changes.\n- Frequent flipping is permitted but produces noisy timelines; use `plan.updated` for non-state edits.\n\n### Related events\n\n- `plan.deactivated`: paired transition.\n- `plan.created`: predecessor.",
                "summary": "Inactive plan flipped active.",
                "tags": [
                    "plan.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "plan.activated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `plan.activated` here.",
                                        "enum": [
                                            "plan.activated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan": {
                                                "type": "object",
                                                "description": "The plan after the change.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Plan identifier."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Display name."
                                                    },
                                                    "price": {
                                                        "type": "string",
                                                        "format": "decimal",
                                                        "description": "Decimal amount as a string, e.g. `\"29.00\"`."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Always `true` for this event."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "price",
                                                    "active"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "plan"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "plan.activated",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan": {
                                                "id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "name": "Premium Monthly",
                                                "price": "29.00",
                                                "active": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "plan"
            }
        },
        "plan.deactivated": {
            "post": {
                "operationId": "webhook.plan.deactivated",
                "description": "### When this fires\n\nA plan is taken off sale through the REST API (`POST /v1/projects/{project}/plans/{plan}/unpublish`) or the `publish_plan` MCP tool; automatically when a pass series runs its last date; or when the free-plan entitlement sweep disables an unentitled zero-priced plan. The plan remains visible to existing subscribers and stays in the catalog, but new checkouts cannot select it. Deactivating from the creator dashboard does not emit this event.\n\n> **The two shapes are disjoint.** The publish-state path sends `data.plan` and nothing else; an automatically retired series sends the five flat keys and no `data.plan` object. Branch on whether `data.plan` or `data.plan_id` is present before reading any other field.\n\n### Caveats\n\n- Existing subscriptions on the plan are unaffected and continue to renew until cancelled or expired.\n- For permanent removal use `plan.deleted`.\n\n### Related events\n\n- `plan.activated`: paired transition.\n- `plan.deleted`: terminal state.",
                "summary": "Active plan flipped inactive.",
                "tags": [
                    "plan.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "plan.deactivated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `plan.deactivated` here.",
                                        "enum": [
                                            "plan.deactivated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan": {
                                                "type": "object",
                                                "description": "Sent by the publish-state path only; absent when a series retires itself.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Plan identifier."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Display name."
                                                    },
                                                    "price": {
                                                        "type": "string",
                                                        "format": "decimal",
                                                        "description": "Decimal amount as a string, e.g. `\"29.00\"`."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Always `false` for this event."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "price",
                                                    "active"
                                                ]
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Series-retirement payload only. The plan taken off sale."
                                            },
                                            "plan_name": {
                                                "type": "string",
                                                "description": "Series-retirement payload only. Display name of that plan."
                                            },
                                            "reason": {
                                                "type": "string",
                                                "description": "Series-retirement payload only. Currently always `series_exhausted`."
                                            },
                                            "window_count": {
                                                "type": "integer",
                                                "description": "Series-retirement payload only. Number of passes the finished season held."
                                            },
                                            "successor_plan_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "Series-retirement payload only. The next season linked on the series; `null` when none is set."
                                            }
                                        }
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "plan.deactivated",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan": {
                                                "id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "name": "Premium Monthly",
                                                "price": "29.00",
                                                "active": false
                                            }
                                        }
                                    }
                                },
                                "payload-series-retired-automatically": {
                                    "summary": "series retired automatically",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "plan.deactivated",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "plan_name": "Summer Season",
                                            "reason": "series_exhausted",
                                            "window_count": 12,
                                            "successor_plan_id": "b1a7c3d5-2e48-4f60-9a1b-7c5d3e820f94"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "plan"
            }
        },
        "plan.sold_out": {
            "post": {
                "operationId": "webhook.plan.sold_out",
                "description": "### When this fires\n\nA plan carrying a **sales cap** records its last allowed successful purchase, or a `pass_series` plan with a **seat cap** seats its last holder. Subscriby switches the plan off on the spot, records the reason, and fires this event once. The plan disappears from the portal and the bot until the creator switches it back on; existing subscribers are untouched.\n\nA `plan.deactivated` event fires alongside it, carrying the same `reason`, so automations that only watch availability still see the change. Subscribe to this event when you care specifically about \"sold out\": a waitlist, a restock reminder, a celebratory post.\n\n> Switching the plan back on from the dashboard, the API (publish) or the `publish_plan` tool clears the reason and, for a sales cap, restarts the counter at zero, so the same cap sells another batch. Raising or clearing the cap while the plan is on sale also restarts the counter. A seat-capped series keeps its seats taken; raise the seat cap before publishing it again.\n\n### Related events\n\n- `plan.deactivated`: fires at the same moment with the same `reason`.\n- `plan.activated`: the creator switching the plan back on.\n- `pass_series.seats_exhausted`: the season-level view of a filled seat cap.",
                "summary": "A plan hit its sales cap, or a pass series filled its last seat, and Subscriby paused it automatically.",
                "tags": [
                    "plan.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "plan.sold_out"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `plan.sold_out` here.",
                                        "enum": [
                                            "plan.sold_out"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan": {
                                                "type": "object",
                                                "description": "Snapshot of the plan after the pause.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Plan identifier."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Display name."
                                                    },
                                                    "price": {
                                                        "type": "string",
                                                        "format": "decimal",
                                                        "description": "Decimal amount as a string, e.g. `\"49.00\"`."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Always `false` for this event."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "price",
                                                    "active"
                                                ]
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The plan, flat, for consumers that never read the snapshot."
                                            },
                                            "plan_name": {
                                                "type": "string",
                                                "description": "The plan's name at the time of the pause."
                                            },
                                            "reason": {
                                                "type": "string",
                                                "description": "`sales_cap_reached` for a capped plan, `seat_cap_reached` for a season whose seats filled.",
                                                "enum": [
                                                    "sales_cap_reached",
                                                    "seat_cap_reached"
                                                ]
                                            },
                                            "sales_cap": {
                                                "type": "integer",
                                                "description": "The cap that was hit: the plan's sales cap, or the series' seat cap."
                                            },
                                            "sales_cap_sold": {
                                                "type": "integer",
                                                "description": "Purchases counted against that cap when it was hit."
                                            }
                                        },
                                        "required": [
                                            "plan",
                                            "plan_id",
                                            "plan_name",
                                            "reason",
                                            "sales_cap",
                                            "sales_cap_sold"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "plan.sold_out",
                                        "created_at": "2026-09-08T14:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan": {
                                                "id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "name": "Founding Members",
                                                "price": "49.00",
                                                "active": false
                                            },
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "plan_name": "Founding Members",
                                            "reason": "sales_cap_reached",
                                            "sales_cap": 10,
                                            "sales_cap_sold": 10
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "plan"
            }
        },
        "plan.order_changed": {
            "post": {
                "operationId": "webhook.plan.order_changed",
                "description": "### When this fires\n\nA creator drags plans into a new order in the dashboard's **Arrange Storefront Order** dialog and saves, calls `POST /v1/projects/{project}/plans/order`, or runs the `reorder_plans` MCP tool. Resetting to the built-in order fires it too. The event carries the resulting order of every plan currently on sale, so a mirror of the storefront can re-sort itself without a second read.\n\n> The built-in order is passes first, then seasons, then subscriptions, each group cheapest first. Plans created after an arrangement join the end in that order until the creator arranges again, so `plan_ids` on this event may be shorter than the plan list read a week later.\n\n### Related events\n\n- `plan.created`: a new plan joins the end of the storefront.\n- `plan.activated`, `plan.deactivated`: a plan entering or leaving the storefront.",
                "summary": "The creator arranged the order plans appear in on the portal and in the bot, or reset it.",
                "tags": [
                    "plan.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "plan.order_changed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `plan.order_changed` here.",
                                        "enum": [
                                            "plan.order_changed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The same project, flat, for consumers that read `data` alone."
                                            },
                                            "plan_ids": {
                                                "type": "array",
                                                "description": "Every active plan of the project in storefront order: pinned plans first, then the built-in order.",
                                                "items": {
                                                    "type": "string",
                                                    "format": "uuid"
                                                }
                                            }
                                        },
                                        "required": [
                                            "project_id",
                                            "plan_ids"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "plan.order_changed",
                                        "created_at": "2026-09-08T14:10:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "plan_ids": [
                                                "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "b1a7c3d5-2e48-4f60-9a1b-7c5d3e820f94",
                                                "a9d2e4f6-1b3c-4d5e-8f70-2c4e6a8b0d1f"
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "plan"
            }
        },
        "plan.deleted": {
            "post": {
                "operationId": "webhook.plan.deleted",
                "description": "> This is the final event you will receive for the given plan id.\n\n### When this fires\n\nThe plan is removed from the project. It is soft-deleted: the row is retained with `deleted_at` set, so subscription rows that reference it are untouched and continue to honor their existing term. Only deletions made through the REST API (`DELETE /v1/projects/{project}/plans/{plan}`) emit this event; deleting a plan from the creator dashboard does not.\n\n### Caveats\n\n- Reads of the plan after this event return `404`. Existing subscriptions continue to reference the plan id internally.\n- Deleting a plan makes no call to the payment providers. Catalog entries previously created by the plan sync (Stripe prices, PayPal plans, and so on) remain active at the provider and must be archived there manually.\n\n### Related events\n\n- `plan.deactivated`: typical predecessor.\n- `plan.created`: first event in the lifecycle.",
                "summary": "Plan soft-deleted (removed from the catalog).",
                "tags": [
                    "plan.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "plan.deleted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `plan.deleted` here.",
                                        "enum": [
                                            "plan.deleted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan": {
                                                "type": "object",
                                                "description": "The plan as it was before deletion.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Plan identifier."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Display name."
                                                    },
                                                    "price": {
                                                        "type": "string",
                                                        "format": "decimal",
                                                        "description": "Decimal amount as a string, e.g. `\"29.00\"`."
                                                    },
                                                    "currency_id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Currency row id, **not** an ISO 4217 code."
                                                    },
                                                    "billing_cycle": {
                                                        "type": "string",
                                                        "description": "Billing cadence unit.",
                                                        "enum": [
                                                            "day",
                                                            "week",
                                                            "month",
                                                            "year",
                                                            "lifetime"
                                                        ]
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Last-known active flag before deletion."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "price",
                                                    "currency_id",
                                                    "billing_cycle",
                                                    "active"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "plan"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "plan.deleted",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan": {
                                                "id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                                "name": "Premium Monthly",
                                                "price": "29.00",
                                                "currency_id": "8f27a0d4-63be-4915-8c07-1a5d9e34b628",
                                                "billing_cycle": "month",
                                                "active": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "plan"
            }
        },
        "plan.sync_completed": {
            "post": {
                "operationId": "webhook.plan.sync_completed",
                "description": "### When this fires\n\nThe plan finishes syncing to one or more external payment-provider catalogs (Stripe, PayPal, CoinPayments, Razorpay). Fires once per active plan per sync run: a run over a project with twelve active plans emits twelve events. A plan whose providers all failed emits nothing, and inactive plans are never synced.\n\n### Caveats\n\n- Partial failures retry on a follow-up run rather than emitting a separate event per provider; `providers` lists only the providers that succeeded for that plan.\n- Errors during sync surface in the dashboard, not as webhook events.\n\n### Related events\n\n- `plan.created`: predecessor that typically triggers the first sync.\n- `plan.updated`: re-sync trigger when pricing or cadence changes.",
                "summary": "Plan synced to the payment-provider catalog (Stripe, PayPal, CoinPayments or Razorpay).",
                "tags": [
                    "plan.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "plan.sync_completed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `plan.sync_completed` here.",
                                        "enum": [
                                            "plan.sync_completed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan that was synced."
                                            },
                                            "providers": {
                                                "type": "array",
                                                "description": "Slugs of providers the plan now exists on. No other provider is ever synced.",
                                                "items": {
                                                    "type": "string",
                                                    "enum": [
                                                        "stripe",
                                                        "paypal",
                                                        "coinpayments",
                                                        "razorpay"
                                                    ]
                                                }
                                            },
                                            "synced_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the sync run completed (slightly earlier than `created_at`)."
                                            }
                                        },
                                        "required": [
                                            "plan_id",
                                            "providers",
                                            "synced_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "plan.sync_completed",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "providers": [
                                                "stripe",
                                                "paypal"
                                            ],
                                            "synced_at": "2026-05-18T10:04:58Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "plan"
            }
        },
        "pass.window_scheduled": {
            "post": {
                "operationId": "webhook.pass.window_scheduled",
                "description": "### When this fires\n\nA dated access window was created on a pass plan: either generated from the plan's recurrence, or placed by hand from **Manage Access Windows** or [the pass windows endpoint](https://docs.subscriby.net/api/v1/reference/pass-windows).\n\nThis is the event that lets you mirror a schedule outward without polling for it. Every other `pass.*` event describes something happening *to* a window that already exists; this one is the window arriving.\n\n> **Why this matters more once a series is involved.** A [Pass Series](https://docs.subscriby.net/creators/pass-series) can be set to absorb new windows automatically as they are scheduled, and its holders are granted them at no charge. Without this event an integration has no way to learn a season grew except by re-reading the plan: the difference between a synced calendar and a stale one.\n\n### Caveats\n\n- **Editing a schedule regenerates windows in bulk.** Saving a pass plan rebuilds its unsold future windows, so a single edit can emit this many times in quick succession. Batch on your side rather than treating each as an isolated announcement.\n- Regeneration never touches a window somebody bought, a window a series points at, or one a creator pinned, so those are not deleted and re-created, and do not re-emit.\n- `source: manual` windows are never rebuilt by a schedule edit. They fire this once, when placed.\n- Timestamps are UTC. `timezone` is on the payload precisely so you do not have to look the plan up to render them correctly.\n\n### Related events\n\n- `pass.window_opened`: the same window reaching its start time.\n- `pass.window_cancelled`: a window being withdrawn.\n- `pass_series.leg_added`: a rule absorbing a newly-scheduled window into a live season.",
                "summary": "A new access window came into existence on a time-limited pass plan.",
                "tags": [
                    "pass.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass.window_scheduled"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass.window_scheduled` here.",
                                        "enum": [
                                            "pass.window_scheduled"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The pass plan the window belongs to."
                                            },
                                            "window_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The window that was created. This is the id a Pass Series points at."
                                            },
                                            "starts_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Window start, **always UTC**."
                                            },
                                            "ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Window end, always UTC."
                                            },
                                            "timezone": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The IANA zone the schedule was authored in. Render `starts_at`/`ends_at` in this, not UTC. `null` when the plan has no timezone recorded; fall back to UTC."
                                            },
                                            "source": {
                                                "type": "string",
                                                "description": "`generated` (built from the plan's recurrence) or `manual` (placed by hand).",
                                                "enum": [
                                                    "generated",
                                                    "manual"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "plan_id",
                                            "window_id",
                                            "starts_at",
                                            "ends_at",
                                            "timezone",
                                            "source"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass.window_scheduled",
                                        "created_at": "2026-09-01T09:14:22Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "window_id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                            "starts_at": "2026-09-20T13:00:00+00:00",
                                            "ends_at": "2026-09-21T03:00:00+00:00",
                                            "timezone": "America/New_York",
                                            "source": "generated"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "pass"
            }
        },
        "pass.window_opened": {
            "post": {
                "operationId": "webhook.pass.window_opened",
                "description": "### When this fires\n\nA scheduled access window on a time-limited pass plan reached its start time. Everyone holding that window has been admitted to the plan's resources on the connector.\n\nWindows are processed every minute, so this fires within roughly 60 seconds of the advertised start time rather than exactly on it.\n\n> This describes the window, not an individual subscriber. For per-member grants, subscribe to `member.resource_added`, which fires once per subscriber per resource.\n\n### Caveats\n\n- Timestamps are UTC. A pass schedule is authored in the creator's timezone, so rendering these without converting will show the wrong local time to buyers.\n- `subscribers_affected` counts holders who were eligible **at open time**, not at purchase time. Cancelled and paused passes are excluded, so this can be lower than the number sold.\n- Anyone who buys **after** this fires is outside the count entirely; a plan whose sales cutoff is anchored to the window end keeps selling while the window runs. Those admissions arrive as `member.resource_added`, not as a second `pass.window_opened`.\n- A window whose worker was down for its entire span is closed without ever opening. In that case this event never fires and only `pass.window_closed` is emitted.\n\n### Related events\n\n- `pass.window_closed`: paired transition.\n- `member.resource_added`: per-subscriber grant.",
                "summary": "A time-limited pass access window opened and its holders were admitted.",
                "tags": [
                    "pass.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass.window_opened"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass.window_opened` here.",
                                        "enum": [
                                            "pass.window_opened"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The pass plan the window belongs to."
                                            },
                                            "window_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The access window that opened."
                                            },
                                            "starts_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Window start, **always UTC**. Render in the plan's schedule timezone."
                                            },
                                            "ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Window end, always UTC."
                                            },
                                            "subscribers_affected": {
                                                "type": "integer",
                                                "description": "How many holders were admitted. May be `0` if every holder cancelled."
                                            }
                                        },
                                        "required": [
                                            "plan_id",
                                            "window_id",
                                            "starts_at",
                                            "ends_at",
                                            "subscribers_affected"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass.window_opened",
                                        "created_at": "2026-09-20T13:00:04Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "window_id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                            "starts_at": "2026-09-20T13:00:00+00:00",
                                            "ends_at": "2026-09-21T03:00:00+00:00",
                                            "subscribers_affected": 47
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "pass"
            }
        },
        "pass.window_closed": {
            "post": {
                "operationId": "webhook.pass.window_closed",
                "description": "### When this fires\n\nA scheduled access window reached its end time. Everyone who held it has been removed from the plan's resources on the connector. For a single-window pass that also ends the purchase: one purchase buys one window, so there is no next window to roll into. For a Pass Series holder only this date's access is stripped; the subscription ends only when the window that closed was the last date they held.\n\nThis also fires for a window that never opened because the worker was unavailable for its entire span. Such a window is closed rather than opened late, so nobody is admitted to a window that has already finished.\n\n### Caveats\n\n- Timestamps are UTC; convert to the plan's schedule timezone before showing them.\n- A subscription that this close *ends* also emits `subscription.expired`, and `member.churned` when it was the subscriber's last active subscription. A series holder mid-slate emits neither, only `pass_series.leg_completed`. De-duplicate if you consume several of these.\n- A cancelled window does not emit this event. It emits `pass.window_cancelled` instead, with per-holder detail in `pass.holder_moved` and `pass.holder_stranded`.\n\n### Related events\n\n- `pass.window_opened`: paired transition.\n- `member.resource_removed`: per-subscriber revocation.",
                "summary": "A time-limited pass access window ended and its holders were removed.",
                "tags": [
                    "pass.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass.window_closed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass.window_closed` here.",
                                        "enum": [
                                            "pass.window_closed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The pass plan the window belongs to."
                                            },
                                            "window_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The access window that closed."
                                            },
                                            "starts_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Window start, **always UTC**."
                                            },
                                            "ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Window end, always UTC."
                                            },
                                            "subscribers_affected": {
                                                "type": "integer",
                                                "description": "How many holders were settled and had this window's access removed. A holder only has their pass *ended* when this was the last date they held; mid-series holders are included in this count but keep their subscription."
                                            }
                                        },
                                        "required": [
                                            "plan_id",
                                            "window_id",
                                            "starts_at",
                                            "ends_at",
                                            "subscribers_affected"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass.window_closed",
                                        "created_at": "2026-09-21T03:00:02Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "window_id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                            "starts_at": "2026-09-20T13:00:00+00:00",
                                            "ends_at": "2026-09-21T03:00:00+00:00",
                                            "subscribers_affected": 47
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "pass"
            }
        },
        "pass.window_cancelled": {
            "post": {
                "operationId": "webhook.pass.window_cancelled",
                "description": "### When this fires\n\nA creator cancelled a scheduled access window from **Manage Access Windows** or [the cancel endpoint](https://docs.subscriby.net/api/v1/reference/pass-windows): a postponed match, a called-off session. This is never automatic: regeneration, slot edits and plan changes all leave sold windows alone, so cancelling is always a deliberate act.\n\nBy the time this fires every holder has already been resettled. A single-date holder was either moved to the next available window on the same plan, or, when nothing suitable was left, had their pass ended and was told what they paid. A season-ticket holder was moved the same way or lost the one date, as the creator chose (`series_holders`), and was told what the date was worth. The tallies are in the payload, and the per-holder detail arrives as `pass.holder_moved` and `pass.holder_stranded` for ordinary passes, or `pass_series.leg_substituted` and `pass_series.leg_dropped` for season-ticket holders.\n\n> Cancelling cannot be undone. The window keeps its start time permanently, so the same instant can never be re-created on that plan: schedule regeneration skips it and adding it by hand is refused.\n\n### Caveats\n\n- Timestamps are UTC; convert to the plan's schedule timezone before showing them.\n- **The counts exclude holders who were paused, past due, or had already cancelled their own pass.** Those are left bound to the cancelled window and are not resettled or messaged, so reconciling refunds from the tallies alone will miss them.\n- `refund_due` and `legs_dropped` are counts, not lists. Consume `pass.holder_stranded` and `pass_series.leg_dropped` for the identities and amounts, or read `meta.refunds` on the cancel endpoint's response. The creator sees the same list in the dashboard's settlement dialog and in a notice to their inbox and email.\n- No refund is issued by Subscriby. Every holder owed a decision is told the amount and that the decision is the creator's.\n- Cancelling a window that is already **Open** evicts its holders immediately: anyone already admitted is removed from the connector's resources and their invite links stop working within seconds. They are not charged again and receive fresh links automatically ahead of their replacement window.\n- A cancelled window never emits `pass.window_closed`.\n\n### Related events\n\n- `pass.holder_moved`: one per resettled single-date holder.\n- `pass.holder_stranded`: one per single-date holder owed a refund.\n- `pass_series.leg_substituted`: one per season-ticket holder moved.\n- `pass_series.leg_dropped`: one per season-ticket holder who lost the date, with the pro-rata figure.",
                "summary": "A creator cancelled a time-limited pass access window, and its holders were resettled.",
                "tags": [
                    "pass.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass.window_cancelled"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass.window_cancelled` here.",
                                        "enum": [
                                            "pass.window_cancelled"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The pass plan the window belonged to."
                                            },
                                            "window_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The access window that was cancelled."
                                            },
                                            "starts_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Window start, **always UTC**."
                                            },
                                            "ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Window end, always UTC."
                                            },
                                            "rebound": {
                                                "type": "integer",
                                                "description": "Holders moved to another window on the same plan, season-ticket holders included."
                                            },
                                            "refund_due": {
                                                "type": "integer",
                                                "description": "Single-date holders whose pass ended because nothing was available. **These are owed money.**"
                                            },
                                            "legs_dropped": {
                                                "type": "integer",
                                                "description": "Season-ticket holders who lost this one date and keep the rest of their series. **Each is owed the date's worth.**"
                                            },
                                            "series_holders": {
                                                "type": "string",
                                                "description": "The choice applied to season-ticket holders: `substitute` or `drop`."
                                            },
                                            "subscribers_affected": {
                                                "type": "integer",
                                                "description": "`rebound + refund_due + legs_dropped`."
                                            }
                                        },
                                        "required": [
                                            "plan_id",
                                            "window_id",
                                            "starts_at",
                                            "ends_at",
                                            "rebound",
                                            "refund_due",
                                            "legs_dropped",
                                            "series_holders",
                                            "subscribers_affected"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass.window_cancelled",
                                        "created_at": "2026-09-18T09:14:22Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "window_id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                            "starts_at": "2026-09-20T13:00:00+00:00",
                                            "ends_at": "2026-09-20T19:00:00+00:00",
                                            "rebound": 38,
                                            "refund_due": 3,
                                            "legs_dropped": 4,
                                            "series_holders": "drop",
                                            "subscribers_affected": 45
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "pass"
            }
        },
        "pass.holder_queued": {
            "post": {
                "operationId": "webhook.pass.holder_queued",
                "description": "### When this fires\n\nA holder tapped their invite link for a dated window that has not opened yet. The platform holds the join request, and Subscriby records that they are queued: they will be admitted automatically the moment the window opens, whether or not they are at their phone.\n\nThis is the moment a buyer stops being a risk, and it is the one thing about a pass that a creator can still act on beforehand.\n\n> **Bought is not the same as queued.** A purchase and a queued request are different events with different follow-up. Someone who bought but never tapped is relying on noticing a message on the day; someone queued needs nothing at all. Everything in the product that nudges a pass holder (the reminder ladder, the creator's roll call, the manual **Send Reminders** button) targets the first group and skips the second.\n\n### Caveats\n\n- **This fires per join request, not per purchase.** A season-ticket holder queues separately for each of their dates, so one series purchase produces at least one of these per date they tap, often spread over weeks, because the link for the next date is sent in the message that ends the previous one. A plan with more than one gated resource produces one per resource they tap, all carrying the same `window_id`.\n- It does **not** fire when someone taps a link for a window that is already open. That is an immediate admission, not a queued request, and arrives as `member.resource_added`.\n- A holder who never taps produces no event at all. Absence is the signal; see `pass.holder_missed` for the other end of that.\n- Re-queuing does re-emit. The handler re-stamps the queue time and fires this event again on every join request it receives, so treat `subscription_id` + `window_id` as the idempotency key on your side.\n\n### Related events\n\n- `pass.holder_missed`: a holder whose window closed without them joining.\n- `pass.window_opened`: the moment held requests are approved.\n- `member.resource_added`: the per-resource grant that follows.",
                "summary": "A pass holder tapped their invite link and their join request is now held.",
                "tags": [
                    "pass.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass.holder_queued"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass.holder_queued` here.",
                                        "enum": [
                                            "pass.holder_queued"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The purchase the queued request belongs to."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The project user who tapped."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The plan that was **bought**. On a series this is the series plan."
                                            },
                                            "plan_kind": {
                                                "type": "string",
                                                "description": "Tells you whether this is one purchase's only date or one leg of a season.",
                                                "enum": [
                                                    "pass",
                                                    "pass_series"
                                                ]
                                            },
                                            "window_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The window they queued for."
                                            },
                                            "source_plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The plan the **window** belongs to. Equal to `plan_id` on a pass; a source plan on a series."
                                            },
                                            "starts_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Window start, **always UTC**."
                                            },
                                            "ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Window end, always UTC."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "plan_kind",
                                            "window_id",
                                            "source_plan_id",
                                            "starts_at",
                                            "ends_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass.holder_queued",
                                        "created_at": "2026-09-17T18:42:10Z",
                                        "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",
                                            "plan_kind": "pass",
                                            "window_id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                            "source_plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "starts_at": "2026-09-20T13:00:00+00:00",
                                            "ends_at": "2026-09-21T03:00:00+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "pass"
            }
        },
        "pass.holder_moved": {
            "post": {
                "operationId": "webhook.pass.holder_moved",
                "description": "### When this fires\n\nOne holder of a cancelled access window was moved onto another date. Fires once per resettled holder of an ordinary pass, alongside the single `pass.window_cancelled` for the window itself. A season-ticket holder's move emits `pass_series.leg_substituted` instead; the two are mutually exclusive.\n\nThe replacement is the soonest window on the **same plan** that is still on sale, has not started yet, and that this customer does not already hold a pass for. If the schedule has nothing future left, a window already in progress is used rather than stranding them. Every window on a plan sells for the same price, which is what makes the move an even swap rather than a substitution.\n\nThey are not charged again. If the cancelled window had not opened yet, their existing invite links stay valid for the replacement date; if they had already been admitted to a live window, that access and those links are revoked immediately and fresh links are sent when the replacement window opens.\n\n### Caveats\n\n- Timestamps are UTC; convert to the plan's schedule timezone before showing them.\n- `was_queued` is the field worth branching on. A queued holder keeps their place and is admitted automatically on the new date; an unqueued one still has to tap their link, and is sent it again as a button.\n- Nobody is moved onto a date they already hold. A customer with passes for two consecutive windows skips to the one after.\n- The move is written quietly, so no `subscription.*` event accompanies it. This event is the only signal.\n- Holders who were paused, past due, or had cancelled their own pass are not moved and emit nothing at all.\n\n### Related events\n\n- `pass.window_cancelled`: the window-level event, fired once.\n- `pass.holder_stranded`: the other outcome, when no window was available.",
                "summary": "A pass holder was moved from a cancelled access window to the next available one on the same plan.",
                "tags": [
                    "pass.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass.holder_moved"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass.holder_moved` here.",
                                        "enum": [
                                            "pass.holder_moved"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The pass purchase that moved."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The subscriber holding it."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The pass plan. Unchanged by the move."
                                            },
                                            "from_window_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The cancelled window."
                                            },
                                            "from_starts_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Cancelled window start, **always UTC**."
                                            },
                                            "from_ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Cancelled window end, always UTC."
                                            },
                                            "to_window_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The window they now hold."
                                            },
                                            "to_starts_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "New window start, always UTC."
                                            },
                                            "to_ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "New window end, always UTC."
                                            },
                                            "was_queued": {
                                                "type": "boolean",
                                                "description": "`true` if they had already tapped their invite link, so the move asks nothing of them."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "from_window_id",
                                            "from_starts_at",
                                            "from_ends_at",
                                            "to_window_id",
                                            "to_starts_at",
                                            "to_ends_at",
                                            "was_queued"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass.holder_moved",
                                        "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",
                                            "to_window_id": "9a41f0be-27d5-4c18-b3ea-70d5c8194ef2",
                                            "to_starts_at": "2026-09-27T13:00:00+00:00",
                                            "to_ends_at": "2026-09-27T19:00:00+00:00",
                                            "was_queued": true
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "pass"
            }
        },
        "pass.holder_missed": {
            "post": {
                "operationId": "webhook.pass.holder_missed",
                "description": "### When this fires\n\nAn access window closed and a specific holder was recorded as **Missed**: they paid, the window ran, and they never joined.\n\n`pass.window_closed` already reports an aggregate `subscribers_affected`, which is the wrong half for outreach. Who did not turn up is the useful question, the answer is already computed and stored per holder, and this is that answer.\n\n> **Missed is a claim about the customer, so it is made carefully.** A holder is only marked Missed when they were never admitted. If they bought so late that the window was effectively over before their payment cleared, the pass is settled as ended rather than missed and **this event does not fire**; Subscriby will not tell you a paying customer no-showed when the timing was ours. One exception runs the other way: when a window never opened at all because of a worker outage, its ungranted holders *are* recorded as Missed and this event fires for each of them, so treat a burst of these for a single window as an outage signal rather than as no-shows.\n\n### Caveats\n\n- `join_requested` is the field worth branching on. A holder who never queued probably never saw the message; that is a reachability problem. A holder who queued and still did not appear made a choice, and chasing them the same way reads as nagging.\n- **On a series this fires per date.** Missing one date of a season affects nothing else: the rest of the slate runs as booked, so treat a single occurrence as a data point rather than a churn signal. `pass_series.completed` carries the final tally, which is the figure that actually means something.\n- It fires alongside `pass.window_closed` for the same window. Both are correct (one is per holder, one is the aggregate) so an endpoint subscribed to both receives one of each.\n\n### Related events\n\n- `pass.holder_queued`: the engagement this is the absence of.\n- `pass.window_closed`: the aggregate for the same window.\n- `pass_series.leg_completed`: the same close, seen as progress through a season.",
                "summary": "A window closed and one holder never turned up for it.",
                "tags": [
                    "pass.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass.holder_missed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass.holder_missed` here.",
                                        "enum": [
                                            "pass.holder_missed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The purchase that went unused."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The project user who did not turn up."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The plan the **window** belongs to."
                                            },
                                            "window_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The window they missed."
                                            },
                                            "starts_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Window start, **always UTC**."
                                            },
                                            "ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Window end, always UTC."
                                            },
                                            "join_requested": {
                                                "type": "boolean",
                                                "description": "Whether they ever tapped their invite link. `false` means they never engaged at all; `true` means they queued and still did not appear."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "window_id",
                                            "starts_at",
                                            "ends_at",
                                            "join_requested"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass.holder_missed",
                                        "created_at": "2026-09-21T03:00:07Z",
                                        "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",
                                            "window_id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                            "starts_at": "2026-09-20T13:00:00+00:00",
                                            "ends_at": "2026-09-21T03:00:00+00:00",
                                            "join_requested": false
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "pass"
            }
        },
        "pass.holder_stranded": {
            "post": {
                "operationId": "webhook.pass.holder_stranded",
                "description": "### When this fires\n\nOne 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.\n\nThey 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**.\n\n> **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.\n\n### Why a replacement can be missing\n\n- The plan has no later window scheduled at all.\n- The only later windows are already inside the plan's [sales cutoff](https://docs.subscriby.net/creators/time-limited-passes#use-the-sales-cutoff-to-control-this), so they are closed to sales and cannot take new holders; a later date can be visible on the calendar and still not qualify.\n- The customer already holds a pass for every remaining window.\n- The plan's repeating schedule has passed its recurrence end date, so no later window qualifies even if the calendar still shows dates.\n\n### Caveats\n\n- The subscription also emits `subscription.expired`, and `member.churned` when it was their last active subscription. De-duplicate if you consume several.\n- No `subscription.refunded` follows unless the creator actually issues the refund in their payment provider, at which point the gateway's webhook records it.\n- 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.\n- `amount_paid` is what the subscription recorded at purchase; it does not account for any partial refund already issued.\n\n### Related events\n\n- `pass.window_cancelled`: the window-level event, fired once.\n- `pass.holder_moved`: the other outcome, when a replacement existed.\n- `subscription.expired`: also fires for this subscription.",
                "summary": "A pass holder's window was cancelled with no replacement available, so their pass ended and a refund is owed.",
                "tags": [
                    "pass.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass.holder_stranded"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass.holder_stranded` here.",
                                        "enum": [
                                            "pass.holder_stranded"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The pass purchase that ended."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The subscriber owed a refund."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The pass plan."
                                            },
                                            "from_window_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The cancelled window they held."
                                            },
                                            "from_starts_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Cancelled window start, **always UTC**."
                                            },
                                            "from_ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Cancelled window end, always UTC."
                                            },
                                            "refund_due": {
                                                "type": "boolean",
                                                "description": "Always `true`. Present so a single handler can branch on it."
                                            },
                                            "amount_paid": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "What they paid for the window. A string to preserve precision."
                                            },
                                            "currency": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "ISO 4217 code, e.g. `GBP`. Null if the subscription has no currency recorded."
                                            },
                                            "payment_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The gateway's own reference, for issuing the refund. Null when none was recorded."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "from_window_id",
                                            "from_starts_at",
                                            "from_ends_at",
                                            "refund_due",
                                            "amount_paid",
                                            "currency",
                                            "payment_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "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"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "pass"
            }
        },
        "pass_series.purchased": {
            "post": {
                "operationId": "webhook.pass_series.purchased",
                "description": "### When this fires\n\nA [Pass Series](https://docs.subscriby.net/creators/pass-series) was bought, or comped with an access code, and every date on the slate has been written into the buyer's ledger. They hold all of them from this moment; there is nothing further to claim.\n\n> **This fires in addition to `subscription.activated`.** A series **is** a subscription row, so a purchase emits both. An endpoint subscribed to the two receives **two deliveries for one purchase** and must de-duplicate on `subscription_id`. That is not a quirk to work around: `subscription.activated` is what you want for revenue, and this is what you want for the slate. They answer different questions about the same event.\n\n### Caveats\n\n- **`passes_granted + passes_already_held = passes_total`.** Buying a date you already own is allowed on purpose; it is de-duplicated at grant time rather than refused, and the buyer is told so on their timeline. A non-zero `passes_already_held` is normal, not an error.\n- `passes_total` counts what this buyer received, which on a mid-season purchase is **fewer than the slate holds**: dates that have already run are never issued. Read the plan if you need the full slate length.\n- The span is the **series'**, not this buyer's. `starts_at` and `ends_at` are the plan's cached slate span, so on a mid-season purchase `starts_at` can precede every date the buyer actually holds. Only the `passes_*` counts are buyer-scoped.\n- A series absorbing new dates later does not re-emit this. That is `pass_series.leg_added`.\n\n### Related events\n\n- `subscription.activated`: the same purchase as revenue. De-duplicate on `subscription_id`.\n- `pass_series.leg_completed`: one date of this slate finishing.\n- `pass_series.completed`: the final date finishing.\n- `pass_series.seats_exhausted`: when a purchase takes the last seat.",
                "summary": "Someone bought a season ticket and their whole slate was issued.",
                "tags": [
                    "pass_series.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass_series.purchased"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass_series.purchased` here.",
                                        "enum": [
                                            "pass_series.purchased"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The purchase. **De-duplicate on this** against `subscription.activated`."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The project user who bought."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The series plan."
                                            },
                                            "plan_name": {
                                                "type": "string",
                                                "description": "Its name at purchase time."
                                            },
                                            "passes_total": {
                                                "type": "integer",
                                                "description": "How many dates this purchase covers."
                                            },
                                            "passes_granted": {
                                                "type": "integer",
                                                "description": "Dates newly issued to them."
                                            },
                                            "passes_already_held": {
                                                "type": "integer",
                                                "description": "Dates they already held individually. Not issued twice and not charged twice."
                                            },
                                            "starts_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "The **whole slate's** first date start, not this buyer's first date. Always UTC."
                                            },
                                            "ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "The whole slate's last date end, not this buyer's last date. Always UTC."
                                            },
                                            "seat_cap": {
                                                "type": [
                                                    "integer",
                                                    "null"
                                                ],
                                                "description": "The series seat limit, or `null` when uncapped."
                                            },
                                            "seats_remaining": {
                                                "type": [
                                                    "integer",
                                                    "null"
                                                ],
                                                "description": "Seats left after this purchase, or `null` when uncapped."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "plan_name",
                                            "passes_total",
                                            "passes_granted",
                                            "passes_already_held",
                                            "starts_at",
                                            "ends_at",
                                            "seat_cap",
                                            "seats_remaining"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass_series.purchased",
                                        "created_at": "2026-09-01T11:03:44Z",
                                        "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",
                                            "plan_name": "Autumn Season Ticket",
                                            "passes_total": 10,
                                            "passes_granted": 9,
                                            "passes_already_held": 1,
                                            "starts_at": "2026-09-20T13:00:00Z",
                                            "ends_at": "2026-11-29T22:00:00Z",
                                            "seat_cap": 50,
                                            "seats_remaining": 13
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "pass_series"
            }
        },
        "pass_series.leg_added": {
            "post": {
                "operationId": "webhook.pass_series.leg_added",
                "description": "### When this fires\n\nA [Pass Series](https://docs.subscriby.net/creators/pass-series) with **Automatic Passes Selection** matched a newly-scheduled window on one of its source plans, added it to the slate, and granted it to everyone currently holding the series, at no extra charge.\n\nThis is the event that makes an external calendar or CRM worth wiring up. A season composed with rules is not fixed at the point it sold: it grows, and holders are given what it grows by. Without this you would have to re-read the plan to notice.\n\n> **Holders are messaged too.** Every current holder receives a message on the connector naming the new date, and it appears on their timetable and in their calendar feed. Nothing is asked of them; their invite link arrives before it opens, as usual.\n\n### Caveats\n\n- **This fires once per window.** One absorption run can take in several at a time, which arrives as several events rather than one carrying a list.\n- **Absorption respects Prevent Overlapping Passes.** With the toggle on, a window that clashes with something already on the slate is refused rather than absorbed (the series will not hand holders two things at the same time) so a matching window can exist and never produce this event.\n- A rule of type `next_n` stops once it has taken its count and **never tops itself back up**. A window becoming free later does not make it reach for another.\n- A series is capped at 120 dates. A rule that would take the slate past the cap stops there.\n- Holders who cancelled are not granted the new date.\n- Manually handpicked dates never produce this event. Handpicking is a fixed list by design; only rules keep working after the save.\n- A date the creator has excluded stays excluded. Unticking a rule-added pass records a permanent exclusion, and the rule will not put it back.\n\n### Related events\n\n- `pass.window_scheduled`: the window coming into existence, which is what a rule reacts to.\n- `pass_series.leg_substituted`: a date being swapped rather than added.\n- `pass_series.leg_dropped`: a date leaving a season.",
                "summary": "An automatic rule absorbed a newly-scheduled window into a live series.",
                "tags": [
                    "pass_series.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass_series.leg_added"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass_series.leg_added` here.",
                                        "enum": [
                                            "pass_series.leg_added"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The **series** plan that grew."
                                            },
                                            "plan_name": {
                                                "type": "string",
                                                "description": "Its name."
                                            },
                                            "window_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The window that was absorbed."
                                            },
                                            "source_plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The pass plan the window belongs to. This is the plan whose resources that date grants."
                                            },
                                            "starts_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Window start, **always UTC**."
                                            },
                                            "ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Window end, always UTC."
                                            },
                                            "timezone": {
                                                "type": "string",
                                                "description": "The **source plan's** authoring zone; a series has none of its own. Render the timestamps in this."
                                            },
                                            "window_count": {
                                                "type": "integer",
                                                "description": "The slate's total length after this absorption."
                                            }
                                        },
                                        "required": [
                                            "plan_id",
                                            "plan_name",
                                            "window_id",
                                            "source_plan_id",
                                            "starts_at",
                                            "ends_at",
                                            "timezone",
                                            "window_count"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass_series.leg_added",
                                        "created_at": "2026-10-04T07:15:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "plan_name": "Autumn Season Ticket",
                                            "window_id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                            "source_plan_id": "9a4c1b58-2e37-4d80-b6f1-0c7e35a92b41",
                                            "starts_at": "2026-11-08T18:00:00Z",
                                            "ends_at": "2026-11-08T21:00:00Z",
                                            "timezone": "America/New_York",
                                            "window_count": 12
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "pass_series"
            }
        },
        "pass_series.leg_completed": {
            "post": {
                "operationId": "webhook.pass_series.leg_completed",
                "description": "### When this fires\n\nOne window on a season ticket closed for one holder. It fires per holder per date, so a ten-date season sold to forty people emits four hundred of these across its run.\n\nIt is the progress event. Where `pass.holder_missed` answers \"did they turn up\", this answers \"where are they in the season\", which is what an integration syncing a timetable or scoring engagement actually needs.\n\n### Caveats\n\n- **`granted` and `joined` are tracked separately on purpose.** Granted means Subscriby admitted them; joined means they actually appeared. A date can be granted and not joined (a held request approved into a channel the person never opened) and that distinction is the difference between a delivery problem and a disengaged customer.\n- `passes_attended + passes_missed` will not equal `passes_total` mid-season. The remainder is dates still ahead, plus any marked as already covered because the holder owned them individually before buying the series.\n- When `passes_remaining` reaches `0`, `pass_series.completed` fires for the same holder in the same pass. Both are emitted; de-duplicate if you only want one.\n- Two holders of the same series reach the same date at different points in their own season if one bought mid-way; the counts are per purchase, never per plan.\n\n### Related events\n\n- `pass_series.completed`: the final date of a holder's season.\n- `pass.holder_missed`: the same close, when they did not turn up.\n- `pass.window_closed`: the window-level aggregate.",
                "summary": "One date of a holder's season finished, with their running attendance.",
                "tags": [
                    "pass_series.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass_series.leg_completed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass_series.leg_completed` here.",
                                        "enum": [
                                            "pass_series.leg_completed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The season ticket."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The holder."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The **series** plan they bought."
                                            },
                                            "window_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The date that just finished."
                                            },
                                            "source_plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The pass plan that date belongs to; a series can mix several."
                                            },
                                            "granted": {
                                                "type": "boolean",
                                                "description": "Whether access was actually issued to them for this date."
                                            },
                                            "joined": {
                                                "type": "boolean",
                                                "description": "Whether they actually joined. **Granted and joined are different questions.**"
                                            },
                                            "passes_total": {
                                                "type": "integer",
                                                "description": "Dates on this holder's slate."
                                            },
                                            "passes_attended": {
                                                "type": "integer",
                                                "description": "How many they have joined so far, including this one."
                                            },
                                            "passes_missed": {
                                                "type": "integer",
                                                "description": "How many they have missed so far."
                                            },
                                            "passes_remaining": {
                                                "type": "integer",
                                                "description": "How many are still ahead of them. `0` means this was their last."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "window_id",
                                            "source_plan_id",
                                            "granted",
                                            "joined",
                                            "passes_total",
                                            "passes_attended",
                                            "passes_missed",
                                            "passes_remaining"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass_series.leg_completed",
                                        "created_at": "2026-10-25T21:00:06Z",
                                        "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",
                                            "window_id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                            "source_plan_id": "9a4c1b58-2e37-4d80-b6f1-0c7e35a92b41",
                                            "granted": true,
                                            "joined": true,
                                            "passes_total": 10,
                                            "passes_attended": 4,
                                            "passes_missed": 1,
                                            "passes_remaining": 5
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "pass_series"
            }
        },
        "pass_series.leg_substituted": {
            "post": {
                "operationId": "webhook.pass_series.leg_substituted",
                "description": "### When this fires\n\nA creator cancelled a window that a season ticket points at, a replacement was available, and one holder was moved onto it. Their season carries on at the same length.\n\nFires **once per holder**, not once per cancellation. Each holder is resettled individually because the outcomes differ: someone already holding the replacement date skips past it to the next one they do not have, and someone with no replacement available is dropped instead.\n\n### Caveats\n\n- **`was_queued` is the field worth branching on.** A holder who was queued stays queued for the new date and is told there is nothing to do. One who was not usually gets their invite link attached, except a holder who had already been admitted to the cancelled window: they also report `was_queued: false`, but their access is revoked and they are told a fresh link arrives when the new window opens, so no link is attached. `was_queued: false` therefore covers two different situations; if you need to tell them apart, check whether the holder currently has access. If you send your own message alongside ours, match that split or you will ask half your audience to do something they have already done.\n- The holder is **never** moved onto a date they already hold. The next one they do not have is chosen instead, so `to_window_id` can be further out than the immediate next window.\n- Three groups are skipped entirely and produce no event: holders who are **paused**, **past due**, or who **cancelled their own series**. They still paid for a date that is not happening. Check subscriptions on that plan before reaching for a refund list.\n- `plan_id` is the **source** plan. To identify the series, read `subscription_id`.\n\n### Related events\n\n- `pass.holder_moved`: the same resettlement on an ordinary single-window pass rather than a series.\n- `pass_series.leg_dropped`: what happens when no replacement exists.\n- `pass.window_cancelled`: fires once, last, carrying both tallies.",
                "summary": "A cancelled date in a season was replaced, and one holder was moved to the replacement.",
                "tags": [
                    "pass_series.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass_series.leg_substituted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass_series.leg_substituted` here.",
                                        "enum": [
                                            "pass_series.leg_substituted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The season ticket that was resettled."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The holder who moved."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The plan the **windows** belong to: the source pass plan, not the series."
                                            },
                                            "from_window_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The cancelled window."
                                            },
                                            "from_starts_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Cancelled window start, **always UTC**."
                                            },
                                            "from_ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Cancelled window end, always UTC."
                                            },
                                            "to_window_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The replacement window they now hold."
                                            },
                                            "to_starts_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Replacement start, always UTC."
                                            },
                                            "to_ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Replacement end, always UTC."
                                            },
                                            "was_queued": {
                                                "type": "boolean",
                                                "description": "Whether they still had a **pending** join request on the cancelled date: tapped their invite link and not yet admitted. Someone already admitted to the cancelled window reports `false` even though they tapped, because admission consumes the request."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "from_window_id",
                                            "from_starts_at",
                                            "from_ends_at",
                                            "to_window_id",
                                            "to_starts_at",
                                            "to_ends_at",
                                            "was_queued"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass_series.leg_substituted",
                                        "created_at": "2026-10-18T16:40:12Z",
                                        "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": "9a4c1b58-2e37-4d80-b6f1-0c7e35a92b41",
                                            "from_window_id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                            "from_starts_at": "2026-10-25T18:00:00Z",
                                            "from_ends_at": "2026-10-25T21:00:00Z",
                                            "to_window_id": "7c0b93af-4d61-42e8-95d3-18ba6e07c254",
                                            "to_starts_at": "2026-11-01T18:00:00Z",
                                            "to_ends_at": "2026-11-01T21:00:00Z",
                                            "was_queued": true
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "pass_series"
            }
        },
        "pass_series.leg_dropped": {
            "post": {
                "operationId": "webhook.pass_series.leg_dropped",
                "description": "### When this fires\n\nA creator cancelled a window that a season ticket points at, **no replacement was available**, and that date simply left one holder's season. The rest of their slate is untouched.\n\nThis is the event that carries money information, and it is the one worth wiring up: it is the only durable record of who is owed what.\n\n> **`refund_per_holder` is a figure, not an action.** Subscriby works out what the date was worth as a share of what the holder paid, and reports it. It does **not** move any money. Nothing is charged or refunded automatically, and nothing in the dashboard marks the subscription as owing. A Zap that reads this as \"already refunded\" will double-refund. A Zap that reads it as \"this is what you owe\" is correct.\n\n### Caveats\n\n- **The figure is per holder, not per cancellation.** Two people can be owed different amounts for the same cancelled date: a mid-season buyer paid the same price for fewer dates, so each of theirs is worth more. Sum the events; do not multiply one by a headcount.\n- `series_ended: true` is worth handling separately. That holder's season is over, and an upsell to \"the next date\" is exactly wrong for someone who has just been told there is not one.\n- The same three groups skipped by substitution are skipped here too: **paused**, **past due**, and holders who cancelled their own series. They produce no event and are absent from any total you compute from these.\n- Refunds are issued from your payment provider's dashboard. See [Refunds](https://docs.subscriby.net/creators/managing-subscriptions#refunds).\n\n### Related events\n\n- `pass.holder_stranded`: the equivalent on an ordinary single-window pass, where the whole purchase ends rather than one date of it.\n- `pass_series.leg_substituted`: what happens when a replacement exists.\n- `pass.window_cancelled`: fires once, last, carrying both tallies.",
                "summary": "A cancelled date left a holder's season with no replacement, carrying the pro-rata figure.",
                "tags": [
                    "pass_series.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass_series.leg_dropped"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass_series.leg_dropped` here.",
                                        "enum": [
                                            "pass_series.leg_dropped"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The season ticket that lost a date."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The holder."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The plan the **window** belonged to: the source pass plan, not the series."
                                            },
                                            "from_window_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The cancelled window."
                                            },
                                            "from_starts_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Cancelled window start, **always UTC**."
                                            },
                                            "from_ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Cancelled window end, always UTC."
                                            },
                                            "passes_remaining": {
                                                "type": "integer",
                                                "description": "How many dates this holder still has ahead of them. `0` means their season is over."
                                            },
                                            "refund_per_holder": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "What this date was worth to this holder. **A figure, not a refund.**"
                                            },
                                            "currency": {
                                                "type": "string",
                                                "description": "ISO code the amounts are in."
                                            },
                                            "amount_paid": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "What they originally paid for the whole season."
                                            },
                                            "series_ended": {
                                                "type": "boolean",
                                                "description": "`true` when this was the last date they had left."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "from_window_id",
                                            "from_starts_at",
                                            "from_ends_at",
                                            "passes_remaining",
                                            "refund_per_holder",
                                            "currency",
                                            "amount_paid",
                                            "series_ended"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass_series.leg_dropped",
                                        "created_at": "2026-10-18T16:40:12Z",
                                        "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": "9a4c1b58-2e37-4d80-b6f1-0c7e35a92b41",
                                            "from_window_id": "3d5a8c72-b016-4e94-8fa7-61c209d4e738",
                                            "from_starts_at": "2026-11-29T18:00:00Z",
                                            "from_ends_at": "2026-11-29T21:00:00Z",
                                            "passes_remaining": 3,
                                            "refund_per_holder": "9.90",
                                            "currency": "USD",
                                            "amount_paid": "99.00",
                                            "series_ended": false
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "pass_series"
            }
        },
        "pass_series.seats_exhausted": {
            "post": {
                "operationId": "webhook.pass_series.seats_exhausted",
                "description": "### When this fires\n\nA purchase took the last seat on a series with a **Seat Limit**. The season is now sold out: its portal card reads **Sold out**, but a checkout already in flight is not blocked; the seat cap is only claimed once the payment lands, so a late buyer can pay, be given nothing, and be told to ask the organiser for a refund. Treat this event as the cue to stop promoting the season yourself.\n\nFires at the transition, once. An endpoint told this on every subsequent read would be told a fact rather than an event.\n\n### Caveats\n\n- **Sold out is not permanent.** A seat is released when a holder cancels or is refunded, and the series goes back on sale, at which point a later purchase can exhaust it again and emit this a second time. Treat it as a state change, not a terminal state.\n- Only holders who actually hold the series consume a seat. A checkout that was started and abandoned, or a payment that never cleared, does not.\n- A series with no **Seat Limit** never emits this at all.\n- Raising the cap does not emit anything. If you are tracking availability, read `seats_remaining` on the plan rather than inferring it from this event alone.\n\n### Related events\n\n- `pass_series.purchased`: every purchase, each carrying `seats_remaining`.\n- `plan.deactivated`: the series coming off sale for good once its dates have run.",
                "summary": "A capped season ticket sold its last seat.",
                "tags": [
                    "pass_series.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass_series.seats_exhausted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass_series.seats_exhausted` here.",
                                        "enum": [
                                            "pass_series.seats_exhausted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The series plan that sold out."
                                            },
                                            "plan_name": {
                                                "type": "string",
                                                "description": "Its name."
                                            },
                                            "seat_cap": {
                                                "type": "integer",
                                                "description": "The limit that was reached."
                                            },
                                            "seats_taken": {
                                                "type": "integer",
                                                "description": "Holders counted against it."
                                            },
                                            "last_subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The purchase that took the final seat."
                                            }
                                        },
                                        "required": [
                                            "plan_id",
                                            "plan_name",
                                            "seat_cap",
                                            "seats_taken",
                                            "last_subscription_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass_series.seats_exhausted",
                                        "created_at": "2026-09-12T14:22:51Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "plan_name": "Autumn Season Ticket",
                                            "seat_cap": 50,
                                            "seats_taken": 50,
                                            "last_subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "pass_series"
            }
        },
        "pass_series.completed": {
            "post": {
                "operationId": "webhook.pass_series.completed",
                "description": "### When this fires\n\nThe last date on one holder's season ticket closed. Their season is over.\n\nFires **per holder**, not per series, because \"finished\" is a fact about a purchase: two people holding the same season reach its end on different dates when one of them bought in late.\n\n> **This is the renewal signal.** The tallies are the half worth acting on. A completion with two of ten attended is a churn signal; the same completion with ten of ten is a renewal one. If the creator linked a next season, the holders-only presale opens around the same moment; see `pass_series.presale_opened`.\n\n### Caveats\n\n- The subscription is expired at this point, which is normal and not a failure. A dated purchase ends when its dates run out.\n- `passes_total` is **this holder's** slate, not the plan's. A mid-season buyer received fewer dates for the same price and their totals reflect that.\n- `passes_attended + passes_missed` can be less than `passes_total` when some dates were already covered by passes the holder owned individually; those were not issued twice.\n- `successor_plan_id` being present does **not** mean the holder has been invited yet. The presale opens when the series retires, which is a separate event.\n- The plan itself is deactivated automatically once its last date has run for everybody. That arrives as `plan.deactivated` with `reason: series_exhausted`.\n\n### Related events\n\n- `pass_series.leg_completed`: each date along the way, including this one.\n- `pass_series.presale_opened`: the invitation to the next season.\n- `plan.deactivated`: the series taking itself off sale.",
                "summary": "A holder reached the last date of their season, with the final attendance tallies.",
                "tags": [
                    "pass_series.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass_series.completed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass_series.completed` here.",
                                        "enum": [
                                            "pass_series.completed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The season ticket that finished."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The holder."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The series plan."
                                            },
                                            "plan_name": {
                                                "type": "string",
                                                "description": "Its name."
                                            },
                                            "passes_total": {
                                                "type": "integer",
                                                "description": "Dates this holder's season covered."
                                            },
                                            "passes_attended": {
                                                "type": "integer",
                                                "description": "How many they joined."
                                            },
                                            "passes_missed": {
                                                "type": "integer",
                                                "description": "How many they did not."
                                            },
                                            "successor_plan_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The next season, if the creator linked one. `null` means there is no follow-on."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "plan_name",
                                            "passes_total",
                                            "passes_attended",
                                            "passes_missed",
                                            "successor_plan_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass_series.completed",
                                        "created_at": "2026-11-29T21:00:06Z",
                                        "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",
                                            "plan_name": "Autumn Season Ticket",
                                            "passes_total": 10,
                                            "passes_attended": 8,
                                            "passes_missed": 2,
                                            "successor_plan_id": "b3e70d21-5f94-4a6c-8127-cd4a91e6f508"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "pass_series"
            }
        },
        "pass_series.presale_opened": {
            "post": {
                "operationId": "webhook.pass_series.presale_opened",
                "description": "### When this fires\n\nA season ticket ran its last date, the creator had linked a **Next Series**, and the holders-only window on that successor opened. Every eligible holder has been messaged with a link straight to it.\n\nFor the length of the window, nobody who did not hold the finished season can buy the successor; the portal and the bot both turn them away and say when it goes on general sale.\n\n> **Who is invited is worked out now, not at checkout.** Nothing is stamped onto a purchase when someone pays. Eligibility is resolved at the moment the presale opens, which is what lets a creator link a successor **months after** the season sold out and still reach everyone who bought it.\n\n### Caveats\n\n- **Fires once per season, ever.** The window's opening is stamped, so a repeated sweep does not re-invite anybody. If you need to reach these people again, do it from your own side.\n- `eligible_holders` counts everyone who bought the finished season and did **not** cancel it, whether or not their subscription has expired; by this point most have, which is the normal case and not a disqualification. Someone who cancelled partway through is excluded: they said they did not want the season.\n- It counts holders resolved for invitation, not messages the platform accepted. A holder who has blocked the bot is included here and did not receive anything.\n- Nothing closes the window explicitly. It lapses at `closes_at` and the successor sells to everyone from then on, with no further event.\n- A successor with no `presale_hours` set produces no presale and no event.\n\n### Related events\n\n- `pass_series.completed`: each holder reaching the end of the finished season.\n- `plan.deactivated`: the finished season coming off sale, with `reason: series_exhausted`.\n- `pass_series.purchased`: a holder taking up the offer.",
                "summary": "A finished season's holders were given first refusal on the next one.",
                "tags": [
                    "pass_series.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pass_series.presale_opened"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `pass_series.presale_opened` here.",
                                        "enum": [
                                            "pass_series.presale_opened"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The season that just finished: the one whose holders are being invited."
                                            },
                                            "plan_name": {
                                                "type": "string",
                                                "description": "Its name."
                                            },
                                            "successor_plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The season now reserved for them."
                                            },
                                            "eligible_holders": {
                                                "type": "integer",
                                                "description": "How many holders were invited."
                                            },
                                            "presale_hours": {
                                                "type": "integer",
                                                "description": "The window's length in hours, as the creator set it."
                                            },
                                            "closes_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the successor goes on general sale, **always UTC**."
                                            }
                                        },
                                        "required": [
                                            "plan_id",
                                            "plan_name",
                                            "successor_plan_id",
                                            "eligible_holders",
                                            "presale_hours",
                                            "closes_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "pass_series.presale_opened",
                                        "created_at": "2026-11-29T21:00:11Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "plan_name": "Autumn Season Ticket",
                                            "successor_plan_id": "b3e70d21-5f94-4a6c-8127-cd4a91e6f508",
                                            "eligible_holders": 38,
                                            "presale_hours": 48,
                                            "closes_at": "2026-12-01T21:00:11Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription-plan:view"
                ],
                "x-webhook-family": "pass_series"
            }
        },
        "coupon.created": {
            "post": {
                "operationId": "webhook.coupon.created",
                "description": "### When this fires\n\nA creator authored a new coupon code over the REST API or via the `create_coupon` MCP tool. Coupons authored in the dashboard or through the bot do not currently emit this event; those surfaces write through the service layer directly.\n\nIt fires on **authoring**, not on availability. A coupon created with a future `starts_at` fires this immediately and only becomes redeemable later, so do not read this as \"a discount is now live\": check `starts_at` and `active`.\n\n> There is no separate event for a coupon becoming redeemable when its `starts_at` passes. Schedule against `starts_at` from this payload if you need that moment.\n\n### Caveats\n\n- **The snapshot carries no redemption counts and no plan restriction.** Counts move independently of the coupon row, and the plan list is a separate relation. Read both from [the coupon endpoint](https://docs.subscriby.net/api/v1/reference/coupons) if you need them.\n- **A coupon can be created already switched off.** `active: false` here is legitimate, not a race: a creator can author a code ahead of a campaign and switch it on later, which emits `coupon.activated`.\n- **`code` is uppercase regardless of what was typed.** A creator entering `blackfriday` gets `BLACKFRIDAY`. Compare case-sensitively against the uppercase form.\n- Timestamps inside `data.coupon` are ISO 8601 **with offset** (`+00:00`), unlike the envelope's `created_at`, which uses `Z`. Both are UTC.\n\n### Related events\n\n- `coupon.updated`: the same snapshot after a change, plus a list of what moved.\n- `coupon.activated` / `coupon.deactivated`: availability flips.\n- `coupon.redeemed`: a subscriber actually used it.",
                "summary": "A new coupon code was authored in a project.",
                "tags": [
                    "coupon.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "coupon.created"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `coupon.created` here.",
                                        "enum": [
                                            "coupon.created"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "coupon": {
                                                "type": "object",
                                                "description": "The coupon snapshot every `coupon.*` lifecycle event carries.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The coupon's UUID. No prefix; only the envelope `id` is prefixed."
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "The redeemable string. **Always uppercase**: stored and compared that way."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Creator-facing label. Never shown to subscribers."
                                                    },
                                                    "discount_type": {
                                                        "type": "string",
                                                        "description": "Whether `discount_value` is a percent or an amount.",
                                                        "enum": [
                                                            "percentage",
                                                            "fixed"
                                                        ]
                                                    },
                                                    "discount_value": {
                                                        "type": "string",
                                                        "format": "decimal",
                                                        "description": "The value exactly as submitted: this event is emitted before the row is read back, so it is `\"25\"`, not `\"25.0000\"`. The other lifecycle events re-read the row and carry four decimal places. Parse as a decimal, never a float."
                                                    },
                                                    "currency_id": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "uuid",
                                                        "description": "`null` on a percentage coupon; set on a fixed-amount one."
                                                    },
                                                    "duration": {
                                                        "type": "string",
                                                        "description": "Which charges the discount applies to. Only `once`, the first payment, is authorable."
                                                    },
                                                    "max_redemptions": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ],
                                                        "description": "Total cap across everyone. `null` means unlimited."
                                                    },
                                                    "max_redemptions_per_user": {
                                                        "type": "integer",
                                                        "description": "Per-subscriber cap. Always at least `1`."
                                                    },
                                                    "minimum_amount": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "decimal",
                                                        "description": "Order floor in the plan's own currency. `null` means no floor. As with `discount_value`, it is the value exactly as submitted here: `\"10\"`, not `\"10.0000\"`."
                                                    },
                                                    "starts_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When it becomes redeemable. `null` means immediately."
                                                    },
                                                    "expires_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When it stops. `null` means it runs until switched off."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Whether the creator has it switched on."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "code",
                                                    "name",
                                                    "discount_type",
                                                    "discount_value",
                                                    "currency_id",
                                                    "duration",
                                                    "max_redemptions",
                                                    "max_redemptions_per_user",
                                                    "minimum_amount",
                                                    "starts_at",
                                                    "expires_at",
                                                    "active"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "coupon"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "coupon.created",
                                        "created_at": "2026-11-20T09:14:02Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "coupon": {
                                                "id": "4b9d3e08-a1f6-4275-9c83-7e01d6a2f594",
                                                "code": "BLACKFRIDAY",
                                                "name": "Black Friday 2026",
                                                "discount_type": "percentage",
                                                "discount_value": "25",
                                                "currency_id": null,
                                                "duration": "once",
                                                "max_redemptions": 500,
                                                "max_redemptions_per_user": 1,
                                                "minimum_amount": null,
                                                "starts_at": "2026-11-27T00:00:00+00:00",
                                                "expires_at": "2026-12-01T00:00:00+00:00",
                                                "active": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-coupon:view"
                ],
                "x-webhook-family": "coupon"
            }
        },
        "coupon.updated": {
            "post": {
                "operationId": "webhook.coupon.updated",
                "description": "### When this fires\n\nA creator changed a coupon's terms: its code, name, discount, caps, minimum, or window. Fires once per update through the REST API.\n\nThe dedicated activate and deactivate endpoints emit `coupon.activated` / `coupon.deactivated` rather than this event. An update that includes `active` is still an update, and emits `coupon.updated` with `active` in its `changes`, so handle `active` appearing in `changes` as well as subscribing to the flip events.\n\n> **Editing terms is dashboard and API only.** The bot can create, inspect, switch off and delete a coupon, but not edit its terms; a multi-field edit is a form, not a chat. Dashboard edits do not currently emit this event (the dashboard writes through the service layer directly), so this event originates from the REST API.\n\n`changes` only contains keys whose value differs. A save that changed nothing sends `\"changes\": {}`; the event still fires, because the creator did press save.\n\n### Caveats\n\n- **`changes` compares the snapshot, not the database columns.** It covers exactly the keys in `data.coupon`, so a change to the coupon's **plan restriction** does not appear; that lives in a separate relation the snapshot deliberately omits. Re-read [the coupon endpoint](https://docs.subscriby.net/api/v1/reference/coupons) if you track which plans a code covers.\n- **`from` and `to` keep their original types.** A decimal field gives you decimal strings, an integer field integers, a nullable field `null`. Don't assume both sides are strings.\n- **Changing the code does not migrate past redemptions.** Redemptions already recorded stay attached to the coupon by id, so a renamed code keeps its history, but any subscriber who wrote the old string down now has a dead code.\n- **A change is not retroactive.** Subscribers who already redeemed keep the terms they paid under; a reduced discount only affects checkouts from here on.\n\n### Related events\n\n- `coupon.created`: the same snapshot shape, on authoring.\n- `coupon.activated` / `coupon.deactivated`: the on/off flip this event deliberately excludes.",
                "summary": "A coupon's terms changed, with a field-by-field list of what moved.",
                "tags": [
                    "coupon.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "coupon.updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `coupon.updated` here.",
                                        "enum": [
                                            "coupon.updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "coupon": {
                                                "type": "object",
                                                "description": "The **new** state, in the same shape every `coupon.*` lifecycle event carries.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The coupon's UUID."
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "The redeemable string, always uppercase."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Creator-facing label."
                                                    },
                                                    "discount_type": {
                                                        "type": "string",
                                                        "description": "Whether `discount_value` is a percent or an amount.",
                                                        "enum": [
                                                            "percentage",
                                                            "fixed"
                                                        ]
                                                    },
                                                    "discount_value": {
                                                        "type": "string",
                                                        "format": "decimal",
                                                        "description": "The discount, read back from the database with four decimal places."
                                                    },
                                                    "currency_id": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "uuid",
                                                        "description": "`null` on a percentage coupon; set on a fixed-amount one."
                                                    },
                                                    "duration": {
                                                        "type": "string",
                                                        "description": "Which charges the discount applies to; only `once` is authorable."
                                                    },
                                                    "max_redemptions": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ],
                                                        "description": "Total cap across everyone. `null` means unlimited."
                                                    },
                                                    "max_redemptions_per_user": {
                                                        "type": "integer",
                                                        "description": "Per-subscriber cap."
                                                    },
                                                    "minimum_amount": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "decimal",
                                                        "description": "Order floor in the plan's own currency, four decimal places; `null` means no floor."
                                                    },
                                                    "starts_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When it becomes redeemable. `null` means immediately."
                                                    },
                                                    "expires_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When it stops. `null` means it runs until switched off."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Whether the creator has it switched on."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "code",
                                                    "name",
                                                    "discount_type",
                                                    "discount_value",
                                                    "currency_id",
                                                    "duration",
                                                    "max_redemptions",
                                                    "max_redemptions_per_user",
                                                    "minimum_amount",
                                                    "starts_at",
                                                    "expires_at",
                                                    "active"
                                                ]
                                            },
                                            "changes": {
                                                "type": "object",
                                                "description": "One entry per field that actually moved, keyed by field name, each `{ \"from\": …, \"to\": … }`. `{}` when nothing moved.",
                                                "additionalProperties": {
                                                    "type": "object",
                                                    "properties": {
                                                        "from": {
                                                            "description": "The previous value, in its original type."
                                                        },
                                                        "to": {
                                                            "description": "The new value, in its original type."
                                                        }
                                                    },
                                                    "required": [
                                                        "from",
                                                        "to"
                                                    ]
                                                }
                                            }
                                        },
                                        "required": [
                                            "coupon",
                                            "changes"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "coupon.updated",
                                        "created_at": "2026-11-24T16:41:11Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "coupon": {
                                                "id": "4b9d3e08-a1f6-4275-9c83-7e01d6a2f594",
                                                "code": "BLACKFRIDAY",
                                                "name": "Black Friday 2026",
                                                "discount_type": "percentage",
                                                "discount_value": "30.0000",
                                                "currency_id": null,
                                                "duration": "once",
                                                "max_redemptions": 1000,
                                                "max_redemptions_per_user": 1,
                                                "minimum_amount": null,
                                                "starts_at": "2026-11-27T00:00:00+00:00",
                                                "expires_at": "2026-12-01T00:00:00+00:00",
                                                "active": true
                                            },
                                            "changes": {
                                                "discount_value": {
                                                    "from": "25.0000",
                                                    "to": "30.0000"
                                                },
                                                "max_redemptions": {
                                                    "from": 500,
                                                    "to": 1000
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-coupon:view"
                ],
                "x-webhook-family": "coupon"
            }
        },
        "coupon.activated": {
            "post": {
                "operationId": "webhook.coupon.activated",
                "description": "### When this fires\n\nA creator switched a coupon **on** through the activate endpoint. Flipping the switch in the dashboard or through the bot does not currently emit this event; those surfaces write through the service layer directly.\n\nThis is the availability flip, kept out of `coupon.updated` on purpose: an automation that cares whether a discount is live wants one event to subscribe to, not a diff of the `active` key on every save.\n\n> **Switched on is not the same as redeemable.** `active: true` is one of four conditions. A coupon still will not apply if it is outside its `starts_at` / `expires_at` window, if every use is already spoken for, or if the buyer has hit their own per-subscriber cap. Check the window and the caps in the payload before announcing a live sale.\n\n### Caveats\n\n- **This is not scheduled.** It fires when a person flips the switch. A coupon whose `starts_at` simply arrived does **not** emit this; nothing changed on the row. If you need the moment a code becomes redeemable, schedule against `starts_at`.\n- **Re-activating a switched-off coupon does not reset its counts.** Redemptions taken before it was switched off still count against `max_redemptions`, so a code that was exhausted before is still exhausted after.\n- **Idempotent flips still emit.** Activating an already-active coupon over the API emits this again. De-dup on the event `id`.\n\n### Related events\n\n- `coupon.deactivated`: the paired transition.\n- `coupon.updated`: a terms change, which deliberately excludes this flip.",
                "summary": "A coupon was switched on and is being offered at checkout again.",
                "tags": [
                    "coupon.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "coupon.activated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `coupon.activated` here.",
                                        "enum": [
                                            "coupon.activated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "coupon": {
                                                "type": "object",
                                                "description": "The same snapshot every `coupon.*` lifecycle event carries. `active` is always `true` here. Read back from the database, so `discount_value` and `minimum_amount` carry four decimal places.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The coupon's UUID."
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "The redeemable string, always uppercase."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Creator-facing label."
                                                    },
                                                    "discount_type": {
                                                        "type": "string",
                                                        "description": "Whether `discount_value` is a percent or an amount.",
                                                        "enum": [
                                                            "percentage",
                                                            "fixed"
                                                        ]
                                                    },
                                                    "discount_value": {
                                                        "type": "string",
                                                        "format": "decimal",
                                                        "description": "The discount, four decimal places."
                                                    },
                                                    "currency_id": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "uuid",
                                                        "description": "`null` on a percentage coupon; set on a fixed-amount one."
                                                    },
                                                    "duration": {
                                                        "type": "string",
                                                        "description": "Which charges the discount applies to; only `once` is authorable."
                                                    },
                                                    "max_redemptions": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ],
                                                        "description": "Total cap across everyone. `null` means unlimited."
                                                    },
                                                    "max_redemptions_per_user": {
                                                        "type": "integer",
                                                        "description": "Per-subscriber cap."
                                                    },
                                                    "minimum_amount": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "decimal",
                                                        "description": "Order floor in the plan's own currency; `null` means no floor."
                                                    },
                                                    "starts_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When it becomes redeemable. `null` means immediately."
                                                    },
                                                    "expires_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When it stops. `null` means it runs until switched off."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Always `true` on this event."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "code",
                                                    "name",
                                                    "discount_type",
                                                    "discount_value",
                                                    "currency_id",
                                                    "duration",
                                                    "max_redemptions",
                                                    "max_redemptions_per_user",
                                                    "minimum_amount",
                                                    "starts_at",
                                                    "expires_at",
                                                    "active"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "coupon"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "coupon.activated",
                                        "created_at": "2026-11-27T00:00:31Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "coupon": {
                                                "id": "4b9d3e08-a1f6-4275-9c83-7e01d6a2f594",
                                                "code": "BLACKFRIDAY",
                                                "name": "Black Friday 2026",
                                                "discount_type": "percentage",
                                                "discount_value": "25.0000",
                                                "currency_id": null,
                                                "duration": "once",
                                                "max_redemptions": 500,
                                                "max_redemptions_per_user": 1,
                                                "minimum_amount": null,
                                                "starts_at": "2026-11-27T00:00:00+00:00",
                                                "expires_at": "2026-12-01T00:00:00+00:00",
                                                "active": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-coupon:view"
                ],
                "x-webhook-family": "coupon"
            }
        },
        "coupon.deactivated": {
            "post": {
                "operationId": "webhook.coupon.deactivated",
                "description": "### When this fires\n\nA creator switched a coupon **off** through the deactivate endpoint. Switching a code off in the dashboard or through the bot does not currently emit this event; those surfaces write through the service layer directly.\n\nThis is the safe way to retire a code, and the one Subscriby points creators at when a delete is refused. Switching off stops the code being offered immediately without touching the redemptions already recorded against it.\n\n> **A checkout already in flight still completes.** Switching off blocks **new** redemptions. A subscriber who already applied the code and is sitting on a payment page still gets their discount; the hold was taken before the switch. Expect a `coupon.redeemed` to arrive shortly *after* this event, and do not treat that as an error.\n\n### Caveats\n\n- **Expiry does not emit this.** A coupon that runs past its `expires_at` stops applying but its `active` flag never changes, so no event fires. If you need the expiry moment, schedule against `expires_at`.\n- **Exhaustion does not emit this either.** A coupon that runs out of uses emits `coupon.exhausted` and stays `active: true`. The two are distinct states: one is a decision, the other an outcome.\n- **Nothing is refunded or revoked.** Subscribers who already redeemed keep what they paid, and their subscriptions are untouched.\n\n### Related events\n\n- `coupon.activated`: the paired transition.\n- `coupon.exhausted`: ran out of uses rather than being switched off.\n- `coupon.deleted`: the destructive alternative, which stops the code resolving.",
                "summary": "A coupon was switched off and stops being offered at checkout.",
                "tags": [
                    "coupon.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "coupon.deactivated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `coupon.deactivated` here.",
                                        "enum": [
                                            "coupon.deactivated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "coupon": {
                                                "type": "object",
                                                "description": "The same snapshot every `coupon.*` lifecycle event carries. `active` is always `false` here. Read back from the database, so `discount_value` and `minimum_amount` carry four decimal places.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The coupon's UUID."
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "The redeemable string, always uppercase."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Creator-facing label."
                                                    },
                                                    "discount_type": {
                                                        "type": "string",
                                                        "description": "Whether `discount_value` is a percent or an amount.",
                                                        "enum": [
                                                            "percentage",
                                                            "fixed"
                                                        ]
                                                    },
                                                    "discount_value": {
                                                        "type": "string",
                                                        "format": "decimal",
                                                        "description": "The discount, four decimal places."
                                                    },
                                                    "currency_id": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "uuid",
                                                        "description": "`null` on a percentage coupon; set on a fixed-amount one."
                                                    },
                                                    "duration": {
                                                        "type": "string",
                                                        "description": "Which charges the discount applies to; only `once` is authorable."
                                                    },
                                                    "max_redemptions": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ],
                                                        "description": "Total cap across everyone. `null` means unlimited."
                                                    },
                                                    "max_redemptions_per_user": {
                                                        "type": "integer",
                                                        "description": "Per-subscriber cap."
                                                    },
                                                    "minimum_amount": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "decimal",
                                                        "description": "Order floor in the plan's own currency; `null` means no floor."
                                                    },
                                                    "starts_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When it becomes redeemable. `null` means immediately."
                                                    },
                                                    "expires_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When it stops. `null` means it runs until switched off."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Always `false` on this event."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "code",
                                                    "name",
                                                    "discount_type",
                                                    "discount_value",
                                                    "currency_id",
                                                    "duration",
                                                    "max_redemptions",
                                                    "max_redemptions_per_user",
                                                    "minimum_amount",
                                                    "starts_at",
                                                    "expires_at",
                                                    "active"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "coupon"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "coupon.deactivated",
                                        "created_at": "2026-12-01T08:02:19Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "coupon": {
                                                "id": "4b9d3e08-a1f6-4275-9c83-7e01d6a2f594",
                                                "code": "BLACKFRIDAY",
                                                "name": "Black Friday 2026",
                                                "discount_type": "percentage",
                                                "discount_value": "25.0000",
                                                "currency_id": null,
                                                "duration": "once",
                                                "max_redemptions": 500,
                                                "max_redemptions_per_user": 1,
                                                "minimum_amount": null,
                                                "starts_at": "2026-11-27T00:00:00+00:00",
                                                "expires_at": "2026-12-01T00:00:00+00:00",
                                                "active": false
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-coupon:view"
                ],
                "x-webhook-family": "coupon"
            }
        },
        "coupon.deleted": {
            "post": {
                "operationId": "webhook.coupon.deleted",
                "description": "### When this fires\n\nA creator deleted a coupon through the delete endpoint. Deletions from the dashboard or the bot do not currently emit this event; those surfaces write through the service layer directly.\n\nThe payload is a snapshot taken **before** the delete, so this is your last chance to record what the code was. Read it and store what you need; the code stops resolving at checkout the moment the delete goes through.\n\n> **The code stops working, the history stays.** The coupon row is soft-deleted and its redemption records are left in place; attribution in your own reporting is not lost. What goes is the code itself: it stops resolving at checkout immediately. To retire a code while keeping it visible to creators, use `coupon.deactivated` instead.\n\n### Caveats\n\n- **A delete can be refused.** If any subscriber holds a live reservation (a checkout in flight with this discount already quoted to a payment provider) Subscriby refuses the delete and asks the creator to switch the code off instead. No event fires in that case, because nothing happened.\n- **The coupon is soft-deleted, not erased.** [The coupon endpoint](https://docs.subscriby.net/api/v1/reference/coupons) currently still resolves it, because the lookup runs unscoped, so do not use a 404 to detect deletion; treat this event as the authoritative signal and store what you need from this payload.\n- **No counts.** As with every lifecycle event, the snapshot omits redemption counts. If you need a final tally, keep a running total from `coupon.redeemed` rather than trying to read one at delete time.\n\n### Related events\n\n- `coupon.deactivated`: the non-destructive way to retire a code.\n- `coupon.created`: the same snapshot shape, at the other end of the life.",
                "summary": "A coupon was removed, carrying its final snapshot.",
                "tags": [
                    "coupon.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "coupon.deleted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `coupon.deleted` here.",
                                        "enum": [
                                            "coupon.deleted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "coupon": {
                                                "type": "object",
                                                "description": "The same snapshot every `coupon.*` lifecycle event carries. It reflects the coupon's state immediately **before** deletion, so `active` may well be `true`. Read back from the database, so `discount_value` and `minimum_amount` carry four decimal places.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The coupon's UUID."
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "The redeemable string, always uppercase."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Creator-facing label."
                                                    },
                                                    "discount_type": {
                                                        "type": "string",
                                                        "description": "Whether `discount_value` is a percent or an amount.",
                                                        "enum": [
                                                            "percentage",
                                                            "fixed"
                                                        ]
                                                    },
                                                    "discount_value": {
                                                        "type": "string",
                                                        "format": "decimal",
                                                        "description": "The discount, four decimal places."
                                                    },
                                                    "currency_id": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "uuid",
                                                        "description": "`null` on a percentage coupon; set on a fixed-amount one."
                                                    },
                                                    "duration": {
                                                        "type": "string",
                                                        "description": "Which charges the discount applies to; only `once` is authorable."
                                                    },
                                                    "max_redemptions": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ],
                                                        "description": "Total cap across everyone. `null` means unlimited."
                                                    },
                                                    "max_redemptions_per_user": {
                                                        "type": "integer",
                                                        "description": "Per-subscriber cap."
                                                    },
                                                    "minimum_amount": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "decimal",
                                                        "description": "Order floor in the plan's own currency; `null` means no floor."
                                                    },
                                                    "starts_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When it became redeemable. `null` means immediately."
                                                    },
                                                    "expires_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When it was to stop. `null` means it ran until switched off."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Whether the creator had it switched on at the moment of deletion."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "code",
                                                    "name",
                                                    "discount_type",
                                                    "discount_value",
                                                    "currency_id",
                                                    "duration",
                                                    "max_redemptions",
                                                    "max_redemptions_per_user",
                                                    "minimum_amount",
                                                    "starts_at",
                                                    "expires_at",
                                                    "active"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "coupon"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "coupon.deleted",
                                        "created_at": "2026-12-04T11:22:47Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "coupon": {
                                                "id": "4b9d3e08-a1f6-4275-9c83-7e01d6a2f594",
                                                "code": "BLACKFRIDAY",
                                                "name": "Black Friday 2026",
                                                "discount_type": "percentage",
                                                "discount_value": "25.0000",
                                                "currency_id": null,
                                                "duration": "once",
                                                "max_redemptions": 500,
                                                "max_redemptions_per_user": 1,
                                                "minimum_amount": null,
                                                "starts_at": "2026-11-27T00:00:00+00:00",
                                                "expires_at": "2026-12-01T00:00:00+00:00",
                                                "active": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-coupon:view"
                ],
                "x-webhook-family": "coupon"
            }
        },
        "coupon.redeemed": {
            "post": {
                "operationId": "webhook.coupon.redeemed",
                "description": "### When this fires\n\nA payment that carried a coupon **settled**. The reservation taken at checkout has been converted into a recorded redemption, and the money has actually moved.\n\nThis is the money event in the family. It is the only `coupon.*` event that carries amounts, and the only one that tells you the code was really used rather than merely offered.\n\n> **It fires on settlement, not on apply.** A subscriber typing a code into checkout does not emit anything. If they abandon the payment, the hold expires and no event ever fires, which is exactly why a `coupon.redeemed` can be trusted as revenue and a \"code applied\" signal could not.\n\n### This is the amount your reporting should use\n\n`final_amount` is what the payment provider charged and what Subscriby's own transaction fee is calculated from. If you mirror revenue into a spreadsheet or a warehouse, use `final_amount`: not the plan's list price, and not `original_amount`.\n\nFires alongside `payment.succeeded` and `subscription.activated` for the same purchase. All three describe one checkout from three angles; only this one knows a discount was involved.\n\n### Caveats\n\n- **Only the first payment is discounted.** Coupons are first-payment-only today, so a renewal on the same subscription charges list price and emits no coupon event. Do not carry `discount_amount` forward into MRR.\n- **`redemptions_count` is read fresh, so it can jump.** Under concurrent checkouts two events may report counts that are not consecutive. Treat it as a gauge, not a sequence number, and never derive ordering from it.\n- **Amounts are decimal strings in the coupon redemption's currency**, which is the plan's currency, not necessarily your dashboard's display currency. Convert before summing across plans.\n- **A redemption can arrive after the code was switched off**, because a checkout already in flight is allowed to complete. This is expected, not a leak.\n- **Percentage and fixed discounts are both rounded to the currency's precision** before charging, so `discount_amount` is the rounded figure that actually moved, not a raw percentage of `original_amount`.\n\n### Related events\n\n- `coupon.exhausted`: emitted immediately after this one when the redemption takes the last use.\n- `payment.succeeded`: the payment itself.\n- `subscription.activated`: the subscription it bought.",
                "summary": "A subscriber's discounted payment settled and the redemption was recorded.",
                "tags": [
                    "coupon.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "coupon.redeemed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `coupon.redeemed` here.",
                                        "enum": [
                                            "coupon.redeemed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "coupon_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The coupon that was redeemed."
                                            },
                                            "code": {
                                                "type": "string",
                                                "description": "The code as stored: uppercase."
                                            },
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The subscription the discounted payment bought."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The subscriber. Resolve name and contact from the API; no payload carries them."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The plan bought."
                                            },
                                            "original_amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "List price before the discount, in `currency_id`."
                                            },
                                            "discount_amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "What came off."
                                            },
                                            "final_amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "What was actually charged. `original_amount − discount_amount`."
                                            },
                                            "currency_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Currency all three amounts are in."
                                            },
                                            "redemptions_count": {
                                                "type": [
                                                    "integer",
                                                    "null"
                                                ],
                                                "description": "Settled redemptions plus reservations not yet released: a denormalised counter bumped when a checkout takes a hold, not when it settles. Read fresh at emission; `null` only if the coupon row disappeared between settlement and emission."
                                            },
                                            "max_redemptions": {
                                                "type": [
                                                    "integer",
                                                    "null"
                                                ],
                                                "description": "The total cap. `null` means unlimited."
                                            }
                                        },
                                        "required": [
                                            "coupon_id",
                                            "code",
                                            "subscription_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "original_amount",
                                            "discount_amount",
                                            "final_amount",
                                            "currency_id",
                                            "redemptions_count",
                                            "max_redemptions"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "coupon.redeemed",
                                        "created_at": "2026-11-28T14:07:52Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "coupon_id": "4b9d3e08-a1f6-4275-9c83-7e01d6a2f594",
                                            "code": "BLACKFRIDAY",
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "original_amount": "40.0000",
                                            "discount_amount": "10.0000",
                                            "final_amount": "30.0000",
                                            "currency_id": "8f27a0d4-63be-4915-8c07-1a5d9e34b628",
                                            "redemptions_count": 137,
                                            "max_redemptions": 500
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-coupon:view"
                ],
                "x-webhook-family": "coupon"
            }
        },
        "coupon.exhausted": {
            "post": {
                "operationId": "webhook.coupon.exhausted",
                "description": "### When this fires\n\nA settled redemption took the **last remaining use** of a capped coupon. Fires immediately after the `coupon.redeemed` that consumed it, in the same emission.\n\nUse it to close a campaign automatically: pull the code out of a landing page, stop an ad, post \"sold out\", or notify the creator that the cap they set has been reached.\n\n> **Only capped coupons can fire this.** A coupon with `max_redemptions: null` is unlimited and never emits this event.\n\n### Exhaustion counts live reservations, so it can un-exhaust\n\nThis is the one behaviour that surprises people. The quota is enforced against settled redemptions **plus reservations whose hold has not expired**, so a coupon can report exhausted while the last few uses are still only held by checkouts in progress.\n\nIf one of those checkouts is abandoned, the hold expires and its use returns to the pool. The coupon becomes redeemable again, and **no event fires for that**, because nothing changed on the coupon row.\n\nThat design is deliberate: it means an abandoned checkout never permanently burns a use, and no sweeper job is needed to reclaim one. The consequence for you is that `coupon.exhausted` is a strong signal but not a permanent state. If your automation does something hard to undo (pausing an ad spend, emailing a list) verify the current state with [the coupon endpoint](https://docs.subscriby.net/api/v1/reference/coupons) first, and read `redemptions.remaining` rather than comparing counts yourself.\n\n> **`redemptions_count` can exceed `max_redemptions`.** The counter is bumped when a checkout takes a hold, not when it settles, and is only decremented when a hold is explicitly released. Lapsed holds the stale-reservation sweep has not yet reclaimed still sit in it, so on this event `redemptions_count` is equal to or greater than `max_redemptions`, never below it. Read `redemptions.remaining` from the API if you need the reservation-aware figure.\n\n### Caveats\n\n- **It can fire more than once for the same coupon.** Exhausted → a hold expires → redeemable → exhausted again is a legitimate sequence. De-dup on the event `id`, not on the coupon id.\n- **A creator raising `max_redemptions` does not emit a matching \"un-exhausted\" event.** That is a `coupon.updated` with `max_redemptions` in its `changes`.\n- **Expiry is a different thing entirely.** A coupon that runs past `expires_at` stops applying without ever being exhausted, and emits nothing.\n\n### Related events\n\n- `coupon.redeemed`: the redemption that consumed the last use; always precedes this.\n- `coupon.updated`: where a raised cap shows up.\n- `coupon.deactivated`: switched off by decision rather than run out by use.",
                "summary": "The last remaining use of a capped coupon was taken.",
                "tags": [
                    "coupon.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "coupon.exhausted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `coupon.exhausted` here.",
                                        "enum": [
                                            "coupon.exhausted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "coupon_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The coupon that ran out."
                                            },
                                            "code": {
                                                "type": "string",
                                                "description": "The code as stored: uppercase."
                                            },
                                            "max_redemptions": {
                                                "type": "integer",
                                                "description": "The cap that was reached. Never `null` on this event."
                                            },
                                            "redemptions_count": {
                                                "type": [
                                                    "integer",
                                                    "null"
                                                ],
                                                "description": "Settled redemptions plus reservations not yet released: the denormalised counter, bumped at hold time, not at settlement. Read fresh at emission."
                                            }
                                        },
                                        "required": [
                                            "coupon_id",
                                            "code",
                                            "max_redemptions",
                                            "redemptions_count"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "coupon.exhausted",
                                        "created_at": "2026-11-30T21:15:08Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "coupon_id": "4b9d3e08-a1f6-4275-9c83-7e01d6a2f594",
                                            "code": "BLACKFRIDAY",
                                            "max_redemptions": 500,
                                            "redemptions_count": 500
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-coupon:view"
                ],
                "x-webhook-family": "coupon"
            }
        },
        "referral.program_updated": {
            "post": {
                "operationId": "webhook.referral.program_updated",
                "description": "### When this fires\n\nA creator saved the programme's settings or switched it on or off, from whichever surface they used. A project holds one programme, so the first save creates it and every later save updates it: the first save reports every field in `changes`, and a switch reports only `active`.\n\n> **A paused programme attributes and rewards nothing.** `active: false` stops links attributing and payments earning at once; the ledger and the payouts stay readable. A programme whose owner's plan no longer includes the Referral Program behaves the same way without any event, because nothing on the row changed.\n\n### Caveats\n\n- **An edit never changes what was already earned.** Every reward row copies the figures it was priced with, so a lowered rate or a longer hold applies to payments from here on, not to the ledger.\n- **`plan_ids` is reported, unlike the coupon snapshot.** It is part of the programme's shape and changes to it appear in `changes`.\n- **Deleting a programme emits nothing.** The ledger beneath it stays, and a delete is refused while affiliates are still owed commissions; the creator records their payouts or switches the programme off instead.\n\n### Related events\n\n- `referral.affiliate_joined`: the first thing that happens once a programme is live.",
                "summary": "A project's Referral Program settings were written, with a field-by-field list of what moved.",
                "tags": [
                    "referral.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "referral.program_updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `referral.program_updated` here.",
                                        "enum": [
                                            "referral.program_updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "program": {
                                                "type": "object",
                                                "description": "The programme as it now stands.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The programme's UUID."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Whether the creator has it switched on."
                                                    },
                                                    "customers_only": {
                                                        "type": "boolean",
                                                        "description": "Whether only members holding a live membership may join."
                                                    },
                                                    "approval_required": {
                                                        "type": "boolean",
                                                        "description": "Whether a member who joins waits for the creator's approval before their code attributes anything."
                                                    },
                                                    "reward_kind": {
                                                        "type": "string",
                                                        "description": "What a referrer earns: membership days, or money the creator pays out.",
                                                        "enum": [
                                                            "free_days",
                                                            "cash"
                                                        ]
                                                    },
                                                    "reward_days": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ],
                                                        "description": "The days a conversion earns the referrer. `null` on a cash programme."
                                                    },
                                                    "commission_type": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "A percentage of each settled payment, or a fixed amount on the first. `null` on a days programme.",
                                                        "enum": [
                                                            "percentage",
                                                            "fixed",
                                                            null
                                                        ]
                                                    },
                                                    "commission_value": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "decimal",
                                                        "description": "The percentage or the amount, four decimal places. `null` on a days programme."
                                                    },
                                                    "commission_currency_id": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "uuid",
                                                        "description": "The currency of a fixed amount. `null` on a percentage, which is earned in each payment's own currency."
                                                    },
                                                    "commission_period_months": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ],
                                                        "description": "How long a percentage keeps earning on one referred member: `0` for the first payment only, `1` to `36` months, `null` for life. Always `0` on a fixed amount."
                                                    },
                                                    "hold_days": {
                                                        "type": "integer",
                                                        "description": "How many days a commission waits before it is payable, `0` to `90`; a full refund inside the window takes it back."
                                                    },
                                                    "minimum_payout": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "decimal",
                                                        "description": "The balance an affiliate reaches before the creator pays, a guide for the creator. `null` means none."
                                                    },
                                                    "friend_reward_kind": {
                                                        "type": "string",
                                                        "description": "What the referred friend receives on their first purchase.",
                                                        "enum": [
                                                            "none",
                                                            "free_days",
                                                            "coupon"
                                                        ]
                                                    },
                                                    "friend_reward_days": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ],
                                                        "description": "The days a friend receives. `null` unless the kind is `free_days`."
                                                    },
                                                    "friend_coupon_id": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "uuid",
                                                        "description": "The coupon applied at the friend's checkout. `null` unless the kind is `coupon`."
                                                    },
                                                    "payout_details_label": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "What the creator asks affiliates for (\"PayPal email\", \"USDT TRC20 address\"). `null` when nothing was set."
                                                    },
                                                    "plan_ids": {
                                                        "type": "array",
                                                        "description": "The plans a referral earns on. **Empty means every plan**, including plans added later; it does not mean none.",
                                                        "items": {
                                                            "type": "string",
                                                            "format": "uuid"
                                                        }
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "active",
                                                    "customers_only",
                                                    "approval_required",
                                                    "reward_kind",
                                                    "reward_days",
                                                    "commission_type",
                                                    "commission_value",
                                                    "commission_currency_id",
                                                    "commission_period_months",
                                                    "hold_days",
                                                    "minimum_payout",
                                                    "friend_reward_kind",
                                                    "friend_reward_days",
                                                    "friend_coupon_id",
                                                    "payout_details_label",
                                                    "plan_ids"
                                                ]
                                            },
                                            "changes": {
                                                "type": "object",
                                                "description": "One entry per field that actually moved, keyed by field name, each `{ \"from\": …, \"to\": … }`. Every field on the first save.",
                                                "additionalProperties": {
                                                    "type": "object",
                                                    "properties": {
                                                        "from": {
                                                            "description": "The previous value, in its original type; `null` on the first save."
                                                        },
                                                        "to": {
                                                            "description": "The new value, in its original type."
                                                        }
                                                    },
                                                    "required": [
                                                        "from",
                                                        "to"
                                                    ]
                                                }
                                            }
                                        },
                                        "required": [
                                            "program",
                                            "changes"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "referral.program_updated",
                                        "created_at": "2026-11-20T09:14:02Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "program": {
                                                "id": "4b9d3e08-a1f6-4275-9c83-7e01d6a2f594",
                                                "active": true,
                                                "customers_only": false,
                                                "approval_required": false,
                                                "reward_kind": "cash",
                                                "reward_days": null,
                                                "commission_type": "percentage",
                                                "commission_value": "20.0000",
                                                "commission_currency_id": null,
                                                "commission_period_months": 12,
                                                "hold_days": 14,
                                                "minimum_payout": null,
                                                "friend_reward_kind": "free_days",
                                                "friend_reward_days": 7,
                                                "friend_coupon_id": null,
                                                "payout_details_label": "PayPal email",
                                                "plan_ids": []
                                            },
                                            "changes": {
                                                "commission_value": {
                                                    "from": "15.0000",
                                                    "to": "20.0000"
                                                },
                                                "hold_days": {
                                                    "from": 30,
                                                    "to": 14
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-referral:view"
                ],
                "x-webhook-family": "referral"
            }
        },
        "referral.affiliate_joined": {
            "post": {
                "operationId": "webhook.referral.affiliate_joined",
                "description": "### When this fires\n\nA member asked to join from the portal or a connector's bot, or the creator enrolled them by hand. `status` says where they stand: `approved` means their code attributes from this moment, `pending` means the programme requires approval and the creator has been told. A member the creator enrols is approved whatever the programme's switches say.\n\n> **A code is minted, never chosen.** Seven characters from an alphabet without `0`, `O`, `1` or `I`, unique within the project. The member shares it through the portal link and the deep link of every connector the project runs.\n\n### Caveats\n\n- **A member joins once.** A second attempt is refused and emits nothing.\n- **A customers-only programme refuses a lead.** A member with no live membership is refused and emits nothing; nothing in this family announces a refusal.\n\n### Related events\n\n- `referral.affiliate_approved`: the creator lets a pending affiliate in.\n- `referral.captured`: their first friend arrives.",
                "summary": "A member joined the Referral Program and was handed a code.",
                "tags": [
                    "referral.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "referral.affiliate_joined"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `referral.affiliate_joined` here.",
                                        "enum": [
                                            "referral.affiliate_joined"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "affiliate": {
                                                "type": "object",
                                                "description": "The affiliate snapshot every `referral.affiliate_*` event carries.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The affiliate's UUID, distinct from the member's."
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "The code they share. **Always uppercase**: stored and compared that way."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "Their standing. Only `approved` earns.",
                                                        "enum": [
                                                            "pending",
                                                            "approved",
                                                            "suspended"
                                                        ]
                                                    },
                                                    "subscriber_id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The member behind the affiliate. Resolve name and contact from the API; no payload carries them."
                                                    },
                                                    "days_balance": {
                                                        "type": "integer",
                                                        "description": "Days earned while they held no live membership, waiting for their next purchase."
                                                    },
                                                    "joined_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When they joined."
                                                    },
                                                    "approved_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When they were approved. `null` while pending."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "code",
                                                    "status",
                                                    "subscriber_id",
                                                    "days_balance",
                                                    "joined_at",
                                                    "approved_at"
                                                ]
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member, repeated at the top level for filtering."
                                            },
                                            "status": {
                                                "type": "string",
                                                "description": "Their standing from the start: `pending` when the programme requires approval and the member joined themselves.",
                                                "enum": [
                                                    "pending",
                                                    "approved"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "affiliate",
                                            "subscriber_id",
                                            "status"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "referral.affiliate_joined",
                                        "created_at": "2026-11-20T09:14:02Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "affiliate": {
                                                "id": "0d1e6a2f-5c83-4b9d-9c21-7e01d6a2f594",
                                                "code": "K7PMQ2X",
                                                "status": "pending",
                                                "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "days_balance": 0,
                                                "joined_at": "2026-11-20T09:14:02+00:00",
                                                "approved_at": null
                                            },
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "status": "pending"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-referral:view"
                ],
                "x-webhook-family": "referral"
            }
        },
        "referral.affiliate_approved": {
            "post": {
                "operationId": "webhook.referral.affiliate_approved",
                "description": "### When this fires\n\nThe creator approved an affiliate. Approving one already approved changes nothing and emits nothing.\n\nThe member is told, with their link and code, when the programme is live.\n\n### Caveats\n\n- **Re-approving a suspended affiliate restores their earning, not the past.** Payments that settled while they were suspended earned nothing and are not revisited.\n\n### Related events\n\n- `referral.affiliate_suspended`: the paired transition.",
                "summary": "A pending or suspended affiliate was approved and their code attributes from now on.",
                "tags": [
                    "referral.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "referral.affiliate_approved"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `referral.affiliate_approved` here.",
                                        "enum": [
                                            "referral.affiliate_approved"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "affiliate": {
                                                "type": "object",
                                                "description": "The same snapshot every `referral.affiliate_*` event carries.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The affiliate's UUID."
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "The code they share, always uppercase."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "Always `approved` here.",
                                                        "enum": [
                                                            "pending",
                                                            "approved",
                                                            "suspended"
                                                        ]
                                                    },
                                                    "subscriber_id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The member behind the affiliate."
                                                    },
                                                    "days_balance": {
                                                        "type": "integer",
                                                        "description": "Days waiting for their next purchase."
                                                    },
                                                    "joined_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When they joined."
                                                    },
                                                    "approved_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When they were approved; set on this event."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "code",
                                                    "status",
                                                    "subscriber_id",
                                                    "days_balance",
                                                    "joined_at",
                                                    "approved_at"
                                                ]
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member, repeated at the top level for filtering."
                                            },
                                            "status": {
                                                "type": "string",
                                                "description": "Always `approved` on this event.",
                                                "enum": [
                                                    "approved"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "affiliate",
                                            "subscriber_id",
                                            "status"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "referral.affiliate_approved",
                                        "created_at": "2026-11-21T10:02:40Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "affiliate": {
                                                "id": "0d1e6a2f-5c83-4b9d-9c21-7e01d6a2f594",
                                                "code": "K7PMQ2X",
                                                "status": "approved",
                                                "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "days_balance": 0,
                                                "joined_at": "2026-11-20T09:14:02+00:00",
                                                "approved_at": "2026-11-21T10:02:40+00:00"
                                            },
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "status": "approved"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-referral:view"
                ],
                "x-webhook-family": "referral"
            }
        },
        "referral.affiliate_suspended": {
            "post": {
                "operationId": "webhook.referral.affiliate_suspended",
                "description": "### When this fires\n\nThe creator suspended an affiliate. Suspending one already suspended changes nothing and emits nothing.\n\n> **Suspension is about the future.** What the affiliate already earned stays on their balance and can still be paid out; nothing is clawed back.\n\n### Caveats\n\n- **Touches already captured stay captured.** A friend who arrived through the code before the suspension keeps their referral row, but a payment of theirs earns nothing while the affiliate is suspended.\n\n### Related events\n\n- `referral.affiliate_approved`: the way back.",
                "summary": "An affiliate was suspended: their code stops attributing and their referrals stop earning.",
                "tags": [
                    "referral.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "referral.affiliate_suspended"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `referral.affiliate_suspended` here.",
                                        "enum": [
                                            "referral.affiliate_suspended"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "affiliate": {
                                                "type": "object",
                                                "description": "The same snapshot every `referral.affiliate_*` event carries.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The affiliate's UUID."
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "The code they shared, always uppercase. It no longer attributes."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "Always `suspended` here.",
                                                        "enum": [
                                                            "pending",
                                                            "approved",
                                                            "suspended"
                                                        ]
                                                    },
                                                    "subscriber_id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The member behind the affiliate."
                                                    },
                                                    "days_balance": {
                                                        "type": "integer",
                                                        "description": "Days waiting for their next purchase; untouched by the suspension."
                                                    },
                                                    "joined_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When they joined."
                                                    },
                                                    "approved_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When they were last approved."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "code",
                                                    "status",
                                                    "subscriber_id",
                                                    "days_balance",
                                                    "joined_at",
                                                    "approved_at"
                                                ]
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member, repeated at the top level for filtering."
                                            },
                                            "status": {
                                                "type": "string",
                                                "description": "Always `suspended` on this event.",
                                                "enum": [
                                                    "suspended"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "affiliate",
                                            "subscriber_id",
                                            "status"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "referral.affiliate_suspended",
                                        "created_at": "2026-12-02T15:30:11Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "affiliate": {
                                                "id": "0d1e6a2f-5c83-4b9d-9c21-7e01d6a2f594",
                                                "code": "K7PMQ2X",
                                                "status": "suspended",
                                                "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "days_balance": 0,
                                                "joined_at": "2026-11-20T09:14:02+00:00",
                                                "approved_at": "2026-11-21T10:02:40+00:00"
                                            },
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "status": "suspended"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-referral:view"
                ],
                "x-webhook-family": "referral"
            }
        },
        "referral.captured": {
            "post": {
                "operationId": "webhook.referral.captured",
                "description": "### When this fires\n\nA member opened the portal or a connector's deep link carrying an affiliate's code, or typed the code at checkout, and every capture rule passed: the programme is live, the code belongs to an approved affiliate of this project, the member is not the affiliate, holds no referral row yet, and has never settled a payment on the project.\n\n> **First touch wins.** A member carries one referral for life on a project. A second code, from anyone, is refused and emits nothing. The touch lasts the attribution window (thirty days by default); a first payment inside it converts the touch, and a touch that sees none expires quietly.\n\n### Caveats\n\n- **A refused capture emits nothing**, whatever the reason: a self-referral, a suspended code, a paused programme, a member who already paid.\n- **Expiry emits nothing either.** A touch past `expires_at` is closed by a nightly sweep and announced nowhere; schedule against `expires_at` if you need the moment.\n\n### Related events\n\n- `referral.converted`: the first payment inside the window.",
                "summary": "A member arrived through an affiliate's link or typed their code, and the touch was recorded.",
                "tags": [
                    "referral.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "referral.captured"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `referral.captured` here.",
                                        "enum": [
                                            "referral.captured"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "referral_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The touch. The same id travels on `referral.converted` and every reward it earns."
                                            },
                                            "affiliate_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Whose code it was."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member who arrived: the friend, not the affiliate."
                                            },
                                            "source": {
                                                "type": "string",
                                                "description": "Which door they came through.",
                                                "enum": [
                                                    "connector_link",
                                                    "portal_link",
                                                    "code_at_checkout"
                                                ]
                                            },
                                            "connector": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector of a deep link (`telegram`). `null` for the portal and for a typed code."
                                            },
                                            "expires_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the touch lapses without a payment."
                                            }
                                        },
                                        "required": [
                                            "referral_id",
                                            "affiliate_id",
                                            "subscriber_id",
                                            "source",
                                            "connector",
                                            "expires_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "referral.captured",
                                        "created_at": "2026-11-22T18:45:09Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "referral_id": "9c1a7b3f-5d80-4e6a-8b45-2a91c4e76f38",
                                            "affiliate_id": "0d1e6a2f-5c83-4b9d-9c21-7e01d6a2f594",
                                            "subscriber_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "source": "connector_link",
                                            "connector": "telegram",
                                            "expires_at": "2026-12-22T18:45:09+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-referral:view"
                ],
                "x-webhook-family": "referral"
            }
        },
        "referral.converted": {
            "post": {
                "operationId": "webhook.referral.converted",
                "description": "### When this fires\n\nThe ledger recorded the first settled payment of a member who holds a touch inside its window, on a plan the programme covers, and the affiliate is approved. Fires once per referral, immediately before the `referral.reward_earned` events the same payment produces.\n\n> **The commission period is fixed here, from the programme as it stands.** A later edit to the programme never shortens or lengthens what this affiliate was promised on this member.\n\n### Caveats\n\n- **A payment on a plan outside the programme's `plan_ids` converts nothing.** The touch stays open until its window closes.\n- **A $0 settlement converts.** A first purchase fully covered by a coupon is a settled payment; a percentage of nothing earns nothing, but days and a fixed amount are earned as usual.\n\n### Related events\n\n- `referral.reward_earned`: what the conversion earned each side.",
                "summary": "A referred member's first payment settled, locking the referral and fixing how long it earns.",
                "tags": [
                    "referral.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "referral.converted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `referral.converted` here.",
                                        "enum": [
                                            "referral.converted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "referral_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referral, as on `referral.captured`."
                                            },
                                            "affiliate_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referrer."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referred member."
                                            },
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The purchase that converted them."
                                            },
                                            "commission_ends_at": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "date-time",
                                                "description": "When the affiliate stops earning on this member. `null` for life; the payment's own instant for a first-payment-only commission and for every days programme."
                                            }
                                        },
                                        "required": [
                                            "referral_id",
                                            "affiliate_id",
                                            "subscriber_id",
                                            "subscription_id",
                                            "commission_ends_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "referral.converted",
                                        "created_at": "2026-11-28T14:07:52Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "referral_id": "9c1a7b3f-5d80-4e6a-8b45-2a91c4e76f38",
                                            "affiliate_id": "0d1e6a2f-5c83-4b9d-9c21-7e01d6a2f594",
                                            "subscriber_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "subscription_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "commission_ends_at": "2027-11-28T14:07:52+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-referral:view"
                ],
                "x-webhook-family": "referral"
            }
        },
        "referral.reward_earned": {
            "post": {
                "operationId": "webhook.referral.reward_earned",
                "description": "### When this fires\n\nThe ledger recorded a settled payment that a live referral earns on: the conversion earns the referrer their days or their first commission and the friend their welcome days; every later payment inside the period earns a percentage referrer another commission. One event per reward row, so a conversion on a programme with a friend reward emits two.\n\n> **Days land at once, money waits.** A days row is `applied` when the member holds an ordinary live membership (the days are banked on it) and `pending` when they hold nothing live, in which case they wait on the affiliate's balance for their next purchase. A money row is `pending` behind the programme's hold with `hold_until` set, or `approved` at once when the hold is zero.\n\n### Caveats\n\n- **A redelivered payment earns nothing twice.** The ledger records a payment once, and a payment that already earned a row writes no second one.\n- **A friend's days need a purchase that can carry them.** A pass or a season cannot be moved, so a friend who converts on one receives no days row at all rather than one that never applies.\n- **Days are never reversed.** A refund unwinds money rows only; days already banked stay banked.\n\n### Related events\n\n- `referral.reward_approved`: the hold passes.\n- `referral.reward_reversed`: a refund takes it back.\n- `payment.succeeded`: the payment itself, from the gateway's side.",
                "summary": "A settled payment earned a referrer, or the referred friend, days or money.",
                "tags": [
                    "referral.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "referral.reward_earned"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `referral.reward_earned` here.",
                                        "enum": [
                                            "referral.reward_earned"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "reward_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The ledger row. The same id travels on `referral.reward_approved` and `referral.reward_reversed`."
                                            },
                                            "referral_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referral it was earned on."
                                            },
                                            "affiliate_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referrer, on both sides' rows: a friend's row is filed under the affiliate who brought them."
                                            },
                                            "beneficiary": {
                                                "type": "string",
                                                "description": "Whose reward it is.",
                                                "enum": [
                                                    "referrer",
                                                    "friend"
                                                ]
                                            },
                                            "kind": {
                                                "type": "string",
                                                "description": "Days or money.",
                                                "enum": [
                                                    "free_days",
                                                    "cash"
                                                ]
                                            },
                                            "days": {
                                                "type": [
                                                    "integer",
                                                    "null"
                                                ],
                                                "description": "The days, on a days row. `null` on a money row."
                                            },
                                            "amount": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "decimal",
                                                "description": "The money, four decimal places, on a money row. `null` on a days row."
                                            },
                                            "currency_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The currency of `amount`: the payment's own for a percentage, the programme's for a fixed amount. `null` on a days row."
                                            },
                                            "status": {
                                                "type": "string",
                                                "description": "Where the row starts: `applied` for days banked on a membership, `pending` for days on a balance or money inside its hold, `approved` for money with no hold.",
                                                "enum": [
                                                    "pending",
                                                    "approved",
                                                    "applied"
                                                ]
                                            },
                                            "hold_until": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "date-time",
                                                "description": "When a held commission becomes payable. `null` on days and on money with no hold."
                                            },
                                            "payment_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The ledger payment that earned it, the key the credit is idempotent on."
                                            }
                                        },
                                        "required": [
                                            "reward_id",
                                            "referral_id",
                                            "affiliate_id",
                                            "beneficiary",
                                            "kind",
                                            "days",
                                            "amount",
                                            "currency_id",
                                            "status",
                                            "hold_until",
                                            "payment_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "referral.reward_earned",
                                        "created_at": "2026-11-28T14:07:52Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "reward_id": "e83d0b16-c5a4-4c39-97f2-5b7e2d401a86",
                                            "referral_id": "9c1a7b3f-5d80-4e6a-8b45-2a91c4e76f38",
                                            "affiliate_id": "0d1e6a2f-5c83-4b9d-9c21-7e01d6a2f594",
                                            "beneficiary": "referrer",
                                            "kind": "cash",
                                            "days": null,
                                            "amount": "10.0000",
                                            "currency_id": "8f27a0d4-63be-4915-8c07-1a5d9e34b628",
                                            "status": "pending",
                                            "hold_until": "2026-12-12T14:07:52+00:00",
                                            "payment_id": "b81c6e0f-27a9-4d3b-93a7-c4e82f164d5b"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-referral:view"
                ],
                "x-webhook-family": "referral"
            }
        },
        "referral.reward_approved": {
            "post": {
                "operationId": "webhook.referral.reward_approved",
                "description": "### When this fires\n\nThe hourly sweep found a money row past its `hold_until` and marked it payable. Fires once per row; a row approved at once because the programme has no hold emits `referral.reward_earned` with `status: approved` and never this event.\n\n### Caveats\n\n- **Payable is not paid.** The creator pays the affiliate outside Subscriby and records it; until then the row counts toward the affiliate's balance and nothing else moves.\n- **The sweep runs hourly**, so a row becomes payable up to an hour after `hold_until`.\n\n### Related events\n\n- `referral.payout_recorded`: the creator pays it.",
                "summary": "A held commission's refund window passed and it is now payable by the creator.",
                "tags": [
                    "referral.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "referral.reward_approved"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `referral.reward_approved` here.",
                                        "enum": [
                                            "referral.reward_approved"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "reward_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The ledger row, as on `referral.reward_earned`."
                                            },
                                            "referral_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referral it was earned on."
                                            },
                                            "affiliate_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referrer who is owed it."
                                            },
                                            "beneficiary": {
                                                "type": "string",
                                                "description": "Always `referrer`: only money is held, and friends earn no money.",
                                                "enum": [
                                                    "referrer"
                                                ]
                                            },
                                            "kind": {
                                                "type": "string",
                                                "description": "Always `cash` on this event.",
                                                "enum": [
                                                    "cash"
                                                ]
                                            },
                                            "days": {
                                                "type": [
                                                    "integer",
                                                    "null"
                                                ],
                                                "description": "Always `null` on this event."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "The money now payable, four decimal places."
                                            },
                                            "currency_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Its currency."
                                            },
                                            "status": {
                                                "type": "string",
                                                "description": "Always `approved` on this event.",
                                                "enum": [
                                                    "approved"
                                                ]
                                            },
                                            "hold_until": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "The instant the hold passed."
                                            },
                                            "payment_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The ledger payment that earned it."
                                            }
                                        },
                                        "required": [
                                            "reward_id",
                                            "referral_id",
                                            "affiliate_id",
                                            "beneficiary",
                                            "kind",
                                            "days",
                                            "amount",
                                            "currency_id",
                                            "status",
                                            "hold_until",
                                            "payment_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "referral.reward_approved",
                                        "created_at": "2026-12-12T15:00:03Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "reward_id": "e83d0b16-c5a4-4c39-97f2-5b7e2d401a86",
                                            "referral_id": "9c1a7b3f-5d80-4e6a-8b45-2a91c4e76f38",
                                            "affiliate_id": "0d1e6a2f-5c83-4b9d-9c21-7e01d6a2f594",
                                            "beneficiary": "referrer",
                                            "kind": "cash",
                                            "days": null,
                                            "amount": "10.0000",
                                            "currency_id": "8f27a0d4-63be-4915-8c07-1a5d9e34b628",
                                            "status": "approved",
                                            "hold_until": "2026-12-12T14:07:52+00:00",
                                            "payment_id": "b81c6e0f-27a9-4d3b-93a7-c4e82f164d5b"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-referral:view"
                ],
                "x-webhook-family": "referral"
            }
        },
        "referral.reward_reversed": {
            "post": {
                "operationId": "webhook.referral.reward_reversed",
                "description": "### When this fires\n\nA payment that had earned a commission was fully refunded or charged back, which Subscriby learns from the same gateway event that emits `payment.refunded`. A row never paid out is reversed in place; a row already paid is answered with a clawback, a second row carrying the negative amount, so the affiliate's balance drops and the creator's next payout nets it off.\n\n> **A partial refund changes nothing.** The creator kept most of the money, and the rule an affiliate can be told is the simple one: only a full refund takes a commission back. Days are never taken back.\n\n### Caveats\n\n- **A redelivered refund writes no second clawback.** The second delivery finds the rows reversed and the clawback written, and touches nothing.\n- **A refund that names its payment touches that payment's commission only.** One that names none unwinds every live commission on the subscription, which is what a refund of \"the last charge\" means.\n\n### Related events\n\n- `payment.refunded`: the refund this followed.\n- `referral.payout_recorded`: where a clawback is netted off.",
                "summary": "A full refund reversed a commission, or clawed back one the creator had already paid.",
                "tags": [
                    "referral.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "referral.reward_reversed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `referral.reward_reversed` here.",
                                        "enum": [
                                            "referral.reward_reversed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "reward_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The commission the refund touched."
                                            },
                                            "referral_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referral it was earned on."
                                            },
                                            "affiliate_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referrer."
                                            },
                                            "amount": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "decimal",
                                                "description": "The commission's own amount, positive, four decimal places."
                                            },
                                            "currency_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "Its currency."
                                            },
                                            "reason": {
                                                "type": "string",
                                                "description": "Why. Only `refund` today."
                                            },
                                            "clawback_reward_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The negative row written against a commission that was already paid out. `null` when the commission was reversed in place."
                                            }
                                        },
                                        "required": [
                                            "reward_id",
                                            "referral_id",
                                            "affiliate_id",
                                            "amount",
                                            "currency_id",
                                            "reason",
                                            "clawback_reward_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "referral.reward_reversed",
                                        "created_at": "2026-12-05T09:20:44Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "reward_id": "e83d0b16-c5a4-4c39-97f2-5b7e2d401a86",
                                            "referral_id": "9c1a7b3f-5d80-4e6a-8b45-2a91c4e76f38",
                                            "affiliate_id": "0d1e6a2f-5c83-4b9d-9c21-7e01d6a2f594",
                                            "amount": "10.0000",
                                            "currency_id": "8f27a0d4-63be-4915-8c07-1a5d9e34b628",
                                            "reason": "refund",
                                            "clawback_reward_id": "1a5d9e34-b628-4915-8c07-8f27a0d463be"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-referral:view"
                ],
                "x-webhook-family": "referral"
            }
        },
        "referral.payout_recorded": {
            "post": {
                "operationId": "webhook.referral.payout_recorded",
                "description": "### When this fires\n\nThe creator recorded a payout against an affiliate, in one currency, from whichever surface they used. The amount is checked against what the affiliate is owed in that currency, then the oldest payable commissions are marked paid while the amount lasts; `rewards_paid` says how many it covered.\n\n> **Subscriby moved no money.** The payout is the creator's own statement that money left, however they agreed to pay the affiliate.\n\n### Caveats\n\n- **A payout above the balance is refused** and emits nothing, as is one of nothing.\n- **A clawback is paid too.** A negative row is covered in its turn, which is how a refund after a payout nets off against the next one.\n\n### Related events\n\n- `referral.reward_approved`: what becomes payable.\n- `referral.reward_reversed`: what gets netted off.",
                "summary": "The creator recorded that they paid an affiliate.",
                "tags": [
                    "referral.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "referral.payout_recorded"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `referral.payout_recorded` here.",
                                        "enum": [
                                            "referral.payout_recorded"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "payout_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The payout row."
                                            },
                                            "affiliate_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The affiliate paid."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "What was paid, four decimal places."
                                            },
                                            "currency_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The currency it was paid in; balances are kept per currency."
                                            },
                                            "reference": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The creator's own reference for the transfer. `null` when none was given."
                                            },
                                            "rewards_paid": {
                                                "type": "integer",
                                                "description": "How many commission rows the payout covered, clawbacks included; a remainder smaller than the next row stays on the balance."
                                            }
                                        },
                                        "required": [
                                            "payout_id",
                                            "affiliate_id",
                                            "amount",
                                            "currency_id",
                                            "reference",
                                            "rewards_paid"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "referral.payout_recorded",
                                        "created_at": "2026-12-15T11:40:27Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "payout_id": "63be4915-8c07-4d3b-1a5d-9e34b6288f27",
                                            "affiliate_id": "0d1e6a2f-5c83-4b9d-9c21-7e01d6a2f594",
                                            "amount": "25.0000",
                                            "currency_id": "8f27a0d4-63be-4915-8c07-1a5d9e34b628",
                                            "reference": "PAYPAL-7G2K1",
                                            "rewards_paid": 3
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-referral:view"
                ],
                "x-webhook-family": "referral"
            }
        },
        "partner.referral_signed_up": {
            "post": {
                "operationId": "webhook.partner.referral_signed_up",
                "description": "### When this fires\n\nSomeone registered a new creator account with the partner's cookie on their browser (set by the partner link for 60 days), typed the partner's code on the sign-up page with no cookie present, or started the platform bot through the partner's deep link, and every capture rule passed: the partner is active, the account is new, it is not the partner's own, and it holds no referral yet.\n\n> **First touch wins.** An account carries one partner referral for life. The cookie beats a typed code, a second code from anyone is refused, and the referral stays open for 180 days: a first paid Starter or Growth invoice inside that window converts it, and one that sees none expires quietly.\n\n### Caveats\n\n- **A refused capture emits nothing**, whatever the reason: a self-referral, a suspended partner, an unknown code, an account that already carries a referral.\n- **A held sign-up still emits this event.** A sign-up that looks like the partner themselves (their own network, an alias of their email, or one link bringing too many sign-ups in a day) is recorded and held for review from the start; it emits `partner.referral_signed_up` like any other, converts and earns silently, and the hold shows nowhere in this family until it is decided.\n- **Expiry emits nothing either.** A referral past `expires_at` is closed by a nightly sweep and announced nowhere; schedule against `expires_at` if you need the moment.\n- **The friend's discount is not in this event.** The referred creator's 20% off their first three months rides on their own account and shows on their invoices; the partner's commission is taken from the discounted total.\n\n### Related events\n\n- `partner.referral_converted`: the first paid invoice inside the window.",
                "summary": "A new creator account arrived through the partner's link, typed the partner's code at sign-up or came in through the platform bot's deep link, and the referral was recorded.",
                "tags": [
                    "partner.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "partner.referral_signed_up"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `partner.referral_signed_up` here.",
                                        "enum": [
                                            "partner.referral_signed_up"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "referral_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referral. The same id travels on `partner.referral_converted` and every reward it earns."
                                            },
                                            "referred_name": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The referred creator's display name, as they gave it at sign-up. **Never their email**, and no id: a partner sees who they brought, not how to reach them."
                                            },
                                            "source": {
                                                "type": "string",
                                                "description": "Which door they came through.",
                                                "enum": [
                                                    "link",
                                                    "code_at_signup",
                                                    "bot_deep_link"
                                                ]
                                            },
                                            "expires_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the referral lapses without a paid plan."
                                            }
                                        },
                                        "required": [
                                            "referral_id",
                                            "referred_name",
                                            "source",
                                            "expires_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "partner.referral_signed_up",
                                        "created_at": "2026-11-20T09:14:02Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "referral_id": "9c1a7b3f-5d80-4e6a-8b45-2a91c4e76f38",
                                            "referred_name": "Ada Lovelace",
                                            "source": "link",
                                            "expires_at": "2027-05-19T09:14:02+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-webhook-family": "partner"
            }
        },
        "partner.referral_converted": {
            "post": {
                "operationId": "webhook.partner.referral_converted",
                "description": "### When this fires\n\nStripe reported a platform invoice of the referred creator paid for more than $0 on a Starter or Growth subscription while the referral was open, and the partner was active. Fires once per referral, immediately before the `partner.reward_earned` the same invoice produces.\n\n> **The $0 trial invoice converts nothing, and neither does the Free plan.** A card on trial is invoiced $0 and a creator on Free is invoiced only fees; the referral waits for the first paid plan invoice inside its window.\n\n### Caveats\n\n- **A referral held for review converts quietly.** When the card that paid the converting invoice matches the partner's own, or when the sign-up was held from the start, the referral is held under review and this event waits: it fires when Subscriby clears the referral, and the commissions written meanwhile are first heard of as `partner.reward_approved`. A rejected review emits `partner.reward_reversed` for each of them instead.\n- **A later move to Free does not end the period.** The creator's fee invoices keep earning until `commission_ends_at`.\n\n### Related events\n\n- `partner.reward_earned`: what the converting invoice earned.",
                "summary": "The referred creator's first paid Starter or Growth invoice settled, locking the referral and fixing what it earns.",
                "tags": [
                    "partner.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "partner.referral_converted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `partner.referral_converted` here.",
                                        "enum": [
                                            "partner.referral_converted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "referral_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referral, as on `partner.referral_signed_up`."
                                            },
                                            "plan": {
                                                "type": "string",
                                                "description": "The plan whose invoice converted it.",
                                                "enum": [
                                                    "starter",
                                                    "growth"
                                                ]
                                            },
                                            "commission_percent": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "The share of each invoice's total before tax the partner earns on this creator, two decimal places (`\"30.00\"`), fixed here from the programme as it stands."
                                            },
                                            "commission_ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the partner stops earning on this creator: the conversion plus the commission period (12 months today)."
                                            }
                                        },
                                        "required": [
                                            "referral_id",
                                            "plan",
                                            "commission_percent",
                                            "commission_ends_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "partner.referral_converted",
                                        "created_at": "2026-11-28T14:07:52Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "referral_id": "9c1a7b3f-5d80-4e6a-8b45-2a91c4e76f38",
                                            "plan": "starter",
                                            "commission_percent": "30.00",
                                            "commission_ends_at": "2027-11-28T14:07:52+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-webhook-family": "partner"
            }
        },
        "partner.reward_earned": {
            "post": {
                "operationId": "webhook.partner.reward_earned",
                "description": "### When this fires\n\nStripe reported an invoice of a converted referral paid, inside the commission period: the converting invoice itself, every renewal after it, an addon invoice, and the fee invoices of a creator who later moved to Free. One event per invoice. The commission is priced from the invoice's total before tax and after any discount, so the referred creator's 20% off their first three months lowers the first three commissions: a Starter month earns `\"9.3600\"` on a `\"31.2000\"` base, then `\"11.7000\"` on `\"39.0000\"`.\n\n> **Money waits.** A commission is born `pending` behind a 30-day hold, so a refund inside the window can take it back; `hold_until` says when it becomes payable.\n\n### Caveats\n\n- **A redelivered invoice earns nothing twice.** A second `invoice.paid` for the same invoice finds its row and writes no other.\n- **A suspended partner earns nothing**, and the invoice is not revisited when they are reinstated.\n- **A referral under review earns silently.** Its rows are written but not announced until the review is decided.\n\n### Related events\n\n- `partner.reward_approved`: the hold passes.\n- `partner.reward_reversed`: a refund takes it back.",
                "summary": "A paid platform invoice of a referred creator earned the partner a commission.",
                "tags": [
                    "partner.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "partner.reward_earned"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `partner.reward_earned` here.",
                                        "enum": [
                                            "partner.reward_earned"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "reward_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The ledger row. The same id travels on `partner.reward_approved`, `partner.reward_credited` and `partner.reward_reversed`."
                                            },
                                            "referral_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referral it was earned on."
                                            },
                                            "invoice_id": {
                                                "type": "string",
                                                "description": "The Stripe invoice that earned it (`in_…`), the key the credit is idempotent on."
                                            },
                                            "base_amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "The invoice's total before tax and after discounts, four decimal places: what the percent was taken of."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "The commission, four decimal places."
                                            },
                                            "currency": {
                                                "type": "string",
                                                "description": "The currency of both amounts, `USD` on every platform invoice."
                                            },
                                            "status": {
                                                "type": "string",
                                                "description": "Always `pending` on this event: every commission waits out the hold.",
                                                "enum": [
                                                    "pending"
                                                ]
                                            },
                                            "hold_until": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the hold passes and the commission becomes payable: the invoice's paid instant plus the hold (30 days today)."
                                            }
                                        },
                                        "required": [
                                            "reward_id",
                                            "referral_id",
                                            "invoice_id",
                                            "base_amount",
                                            "amount",
                                            "currency",
                                            "status",
                                            "hold_until"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "partner.reward_earned",
                                        "created_at": "2026-11-28T14:07:52Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "reward_id": "e83d0b16-c5a4-4c39-97f2-5b7e2d401a86",
                                            "referral_id": "9c1a7b3f-5d80-4e6a-8b45-2a91c4e76f38",
                                            "invoice_id": "in_1QmX8s2eZvKYlo2CkA9v4z1B",
                                            "base_amount": "31.2000",
                                            "amount": "9.3600",
                                            "currency": "USD",
                                            "status": "pending",
                                            "hold_until": "2026-12-28T14:07:52+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-webhook-family": "partner"
            }
        },
        "partner.reward_approved": {
            "post": {
                "operationId": "webhook.partner.reward_approved",
                "description": "### When this fires\n\nThe hourly sweep found a commission past its `hold_until` on a referral that is not under review, and marked it payable. Fires once per row.\n\n### Caveats\n\n- **Payable is not paid.** A partner on Subscriby Credit is credited in the same run, which `partner.reward_credited` announces; a partner paid in cash waits for the monthly run, which pays balances from $50 and announces `partner.payout_recorded`.\n- **The sweep runs hourly**, so a row becomes payable up to an hour after `hold_until`.\n- **A referral still under review approves nothing.** Its rows wait, past their hold, until Subscriby decides the review.\n\n### Related events\n\n- `partner.reward_credited`: settled as Subscriby Credit.\n- `partner.payout_recorded`: settled in cash.",
                "summary": "A held commission's hold passed and it is now payable.",
                "tags": [
                    "partner.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "partner.reward_approved"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `partner.reward_approved` here.",
                                        "enum": [
                                            "partner.reward_approved"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "reward_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The ledger row, as on `partner.reward_earned`."
                                            },
                                            "referral_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referral it was earned on."
                                            },
                                            "invoice_id": {
                                                "type": "string",
                                                "description": "The Stripe invoice that earned it."
                                            },
                                            "base_amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "What the percent was taken of, four decimal places."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "The money now payable, four decimal places."
                                            },
                                            "currency": {
                                                "type": "string",
                                                "description": "`USD`."
                                            },
                                            "status": {
                                                "type": "string",
                                                "description": "Always `approved` on this event.",
                                                "enum": [
                                                    "approved"
                                                ]
                                            },
                                            "hold_until": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "The instant the hold passed."
                                            }
                                        },
                                        "required": [
                                            "reward_id",
                                            "referral_id",
                                            "invoice_id",
                                            "base_amount",
                                            "amount",
                                            "currency",
                                            "status",
                                            "hold_until"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "partner.reward_approved",
                                        "created_at": "2026-12-28T15:00:03Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "reward_id": "e83d0b16-c5a4-4c39-97f2-5b7e2d401a86",
                                            "referral_id": "9c1a7b3f-5d80-4e6a-8b45-2a91c4e76f38",
                                            "invoice_id": "in_1QmX8s2eZvKYlo2CkA9v4z1B",
                                            "base_amount": "31.2000",
                                            "amount": "9.3600",
                                            "currency": "USD",
                                            "status": "approved",
                                            "hold_until": "2026-12-28T14:07:52+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-webhook-family": "partner"
            }
        },
        "partner.reward_credited": {
            "post": {
                "operationId": "webhook.partner.reward_credited",
                "description": "### When this fires\n\nThe hourly sweep, after approving what it could, applied a partner's whole payable balance to their Stripe customer balance in one transaction, for a partner who chose to be paid in Subscriby Credit. One event per ledger row the transaction covered, each carrying the same `balance_transaction_id`. Stripe draws a negative customer balance down on the partner's next invoice automatically, plan, addons and fees alike, so a partner on the Free plan spends it on fees.\n\n> **The credit rail opens separately.** Subscriby Credit is offered to partners once the balance has been verified live; until then a partner chooses a cash rail and this event never fires.\n\n### Caveats\n\n- **Nothing is credited while the balance is zero or negative.** Clawbacks are netted first; a partner who owes more than they are owed is credited nothing until commissions outgrow it.\n- **A credit is final.** A refund after a credit writes a clawback against the next run; the balance already applied is not taken back from Stripe.\n\n### Related events\n\n- `partner.reward_approved`: what became payable.\n- `partner.reward_reversed`: a clawback after a credit.",
                "summary": "A payable commission was applied to the partner's Subscriby balance.",
                "tags": [
                    "partner.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "partner.reward_credited"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `partner.reward_credited` here.",
                                        "enum": [
                                            "partner.reward_credited"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "reward_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The row credited, as on `partner.reward_earned`; a clawback netted off in the same run is announced with its own id."
                                            },
                                            "referral_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referral it was earned on."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "The row's amount, four decimal places; negative on a clawback netted off in this run."
                                            },
                                            "currency": {
                                                "type": "string",
                                                "description": "`USD`."
                                            },
                                            "balance_transaction_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Stripe's customer balance transaction (`cbtxn_…`) the credit landed in, the same on every row of one run."
                                            }
                                        },
                                        "required": [
                                            "reward_id",
                                            "referral_id",
                                            "amount",
                                            "currency",
                                            "balance_transaction_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "partner.reward_credited",
                                        "created_at": "2026-12-28T15:00:04Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "reward_id": "e83d0b16-c5a4-4c39-97f2-5b7e2d401a86",
                                            "referral_id": "9c1a7b3f-5d80-4e6a-8b45-2a91c4e76f38",
                                            "amount": "9.3600",
                                            "currency": "USD",
                                            "balance_transaction_id": "cbtxn_1QmX8s2eZvKYlo2CkA9v4z1B"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-webhook-family": "partner"
            }
        },
        "partner.reward_reversed": {
            "post": {
                "operationId": "webhook.partner.reward_reversed",
                "description": "### When this fires\n\nThe platform charge that earned a commission was refunded in full (`reason: refund`) or disputed (`reason: dispute`), or Subscriby rejected a referral it had held for review (`reason: rejected`). A row never settled is reversed in place; a row already credited or paid is answered with a clawback, a second row carrying the negative amount, so the partner's balance drops and the next credit or payout nets it off. One event per commission touched.\n\n> **A partial refund changes nothing.** Subscriby kept most of the money, and the rule a partner can be told is the simple one: only a full refund or a dispute takes a commission back.\n\n### Caveats\n\n- **A redelivered refund writes no second clawback.** The second delivery finds the rows reversed and the clawback written, and touches nothing.\n- **A dispute reverses on the day it opens**, because the money is withheld from then; a dispute later won is not revisited.\n- **A rejected review reverses every commission the referral earned**, and the referral earns nothing further.\n\n### Related events\n\n- `partner.reward_credited`: where a clawback is netted off on the credit rail.\n- `partner.payout_recorded`: where a clawback is netted off in cash.",
                "summary": "A full refund, a dispute or a rejected review reversed a commission, or clawed back one already settled.",
                "tags": [
                    "partner.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "partner.reward_reversed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `partner.reward_reversed` here.",
                                        "enum": [
                                            "partner.reward_reversed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "reward_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The commission the reversal touched."
                                            },
                                            "referral_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The referral it was earned on."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "The commission's own amount, positive, four decimal places."
                                            },
                                            "currency": {
                                                "type": "string",
                                                "description": "`USD`."
                                            },
                                            "reason": {
                                                "type": "string",
                                                "description": "Why.",
                                                "enum": [
                                                    "refund",
                                                    "dispute",
                                                    "rejected"
                                                ]
                                            },
                                            "clawback_reward_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The negative row written against a commission already credited or paid. `null` when the commission was reversed in place."
                                            }
                                        },
                                        "required": [
                                            "reward_id",
                                            "referral_id",
                                            "amount",
                                            "currency",
                                            "reason",
                                            "clawback_reward_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "partner.reward_reversed",
                                        "created_at": "2026-12-05T09:20:44Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "reward_id": "e83d0b16-c5a4-4c39-97f2-5b7e2d401a86",
                                            "referral_id": "9c1a7b3f-5d80-4e6a-8b45-2a91c4e76f38",
                                            "amount": "9.3600",
                                            "currency": "USD",
                                            "reason": "refund",
                                            "clawback_reward_id": "1a5d9e34-b628-4915-8c07-8f27a0d463be"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-webhook-family": "partner"
            }
        },
        "partner.payout_recorded": {
            "post": {
                "operationId": "webhook.partner.payout_recorded",
                "description": "### When this fires\n\nSubscriby paid a partner who chose a cash rail and recorded it: payouts run monthly for balances of $50 or more, by PayPal, Wise, Remitly or USDT, to the details the partner saved, less the rail's own transfer fee. The amount is checked against what the partner is owed, then the oldest payable rows are marked paid while the amount lasts; `rewards_paid` says how many it covered, clawbacks included.\n\n### Caveats\n\n- **The payout details never travel.** Where the money went, a PayPal email, a wallet address or the bank account a Wise or Remitly transfer was made to, is stored encrypted on the partner's account and appears in no event.\n- **A payout above the balance is refused** and emits nothing, as is one to a partner who chose Subscriby Credit.\n\n### Related events\n\n- `partner.reward_approved`: what becomes payable.\n- `partner.reward_reversed`: what gets netted off.",
                "summary": "Subscriby recorded a cash payout to the partner.",
                "tags": [
                    "partner.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "partner.payout_recorded"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `partner.payout_recorded` here.",
                                        "enum": [
                                            "partner.payout_recorded"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "payout_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The payout row."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "What was paid, four decimal places."
                                            },
                                            "currency": {
                                                "type": "string",
                                                "description": "`USD`."
                                            },
                                            "method": {
                                                "type": "string",
                                                "description": "The rail the money went by. A partner on Subscriby Credit is settled by `partner.reward_credited` and never sees this event.",
                                                "enum": [
                                                    "paypal",
                                                    "wise",
                                                    "remitly",
                                                    "crypto"
                                                ]
                                            },
                                            "reference": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Subscriby's reference for the transfer. `null` when none was recorded."
                                            },
                                            "rewards_paid": {
                                                "type": "integer",
                                                "description": "How many ledger rows the payout covered, clawbacks included; a remainder smaller than the next row stays on the balance."
                                            }
                                        },
                                        "required": [
                                            "payout_id",
                                            "amount",
                                            "currency",
                                            "method",
                                            "reference",
                                            "rewards_paid"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "partner.payout_recorded",
                                        "created_at": "2027-01-05T11:40:27Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "payout_id": "63be4915-8c07-4d3b-1a5d-9e34b6288f27",
                                            "amount": "58.5000",
                                            "currency": "USD",
                                            "method": "paypal",
                                            "reference": "PAYPAL-7G2K1",
                                            "rewards_paid": 5
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-webhook-family": "partner"
            }
        },
        "partner.application_approved": {
            "post": {
                "operationId": "webhook.partner.application_approved",
                "description": "### When this fires\n\nThe owner approved the application on the console. Fires once per approval; a creator whose application was turned down and who applied again gets it on the later approval.\n\n> **Nothing fires when the application is filed.** The creator filed it themselves and the page says it is under review; this event is the first thing an integration hears.\n\n### Caveats\n\n- **The rate here is the floor.** Each commitment the owner verifies and each volume tier reached raises it; listen to `partner.rate_changed` for the moves.\n- **The application's answers never travel.** Who the partner is, where their audience lives and what they committed to stay on the account.\n\n### Related events\n\n- `partner.rate_changed`: every later move of the rate.\n- `partner.referral_signed_up`: the first creator the link brings.",
                "summary": "Subscriby approved the creator's application to the Partner Program: their code is minted, their starting rate is set and their link attributes from this moment.",
                "tags": [
                    "partner.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "partner.application_approved"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `partner.application_approved` here.",
                                        "enum": [
                                            "partner.application_approved"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "partner_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The partner's standing. The same id travels on `partner.application_rejected` and `partner.rate_changed`."
                                            },
                                            "code": {
                                                "type": "string",
                                                "description": "The partner code, seven characters today, the thing every link carries."
                                            },
                                            "commission_percent": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "The rate the partner starts at, two decimal places (`\"5.00\"`): the base, before any commitment is verified."
                                            },
                                            "joined_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the approval happened."
                                            },
                                            "proof_due_at": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "date-time",
                                                "description": "When the proof of every commitment made on the application is due (60 days after approval today). `null` when the application made none."
                                            }
                                        },
                                        "required": [
                                            "partner_id",
                                            "code",
                                            "commission_percent",
                                            "joined_at",
                                            "proof_due_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "partner.application_approved",
                                        "created_at": "2026-11-18T10:02:41Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "partner_id": "2f6c1d0e-9a3b-4c5d-8e7f-6a5b4c3d2e1f",
                                            "code": "K7PQ2MX",
                                            "commission_percent": "5.00",
                                            "joined_at": "2026-11-18T10:02:41+00:00",
                                            "proof_due_at": "2027-01-17T10:02:41+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-webhook-family": "partner"
            }
        },
        "partner.application_rejected": {
            "post": {
                "operationId": "webhook.partner.application_rejected",
                "description": "### When this fires\n\nThe owner rejected the application on the console with a reason. Fires once per rejection; nothing else changes on the account, and a fresh application after the cooling period starts from the creator's answers again.\n\n### Caveats\n\n- **An application inside the cooling period is refused on the page** and emits nothing.\n\n### Related events\n\n- `partner.application_approved`: the other verdict.",
                "summary": "Subscriby turned the creator's application down, with the reason they were given and the day they may apply again.",
                "tags": [
                    "partner.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "partner.application_rejected"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `partner.application_rejected` here.",
                                        "enum": [
                                            "partner.application_rejected"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "partner_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The creator's standing row, kept with its answers for the next application."
                                            },
                                            "reason": {
                                                "type": "string",
                                                "description": "The reason, in the owner's words, as the creator was told it."
                                            },
                                            "reapply_at": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "date-time",
                                                "description": "The day a fresh application is accepted (90 days after the rejection today). `null` for at once."
                                            }
                                        },
                                        "required": [
                                            "partner_id",
                                            "reason",
                                            "reapply_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "partner.application_rejected",
                                        "created_at": "2026-11-18T10:02:41Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "partner_id": "2f6c1d0e-9a3b-4c5d-8e7f-6a5b4c3d2e1f",
                                            "reason": "Your audience is outside the communities we serve today.",
                                            "reapply_at": "2027-02-16T10:02:41+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-webhook-family": "partner"
            }
        },
        "partner.rate_changed": {
            "post": {
                "operationId": "webhook.partner.rate_changed",
                "description": "### When this fires\n\nEvery time the stored rate changes: the owner verified a commitment (`commitment_verified`), the owner or the nightly sweep lapsed one (`commitment_lapsed`), or a conversion carried the partner across a volume tier (`volume_tier`), whether it converted on its own or the owner cleared it from review. A verification that lands on the cap moves nothing and emits nothing.\n\n> **Every move reaches every referral still earning**, written onto each one's `commission_percent`. A drop, which only a withdrawn commitment causes, also recalculates the commissions not yet credited or paid out. The `partner.referral_converted` that crosses a tier carries the rate before the raise, and this event follows it at once.\n\n> **The paying count the tiers read is every referral that converted**, for life: a creator who later cancels, or whose commission months end, still counts, and a refund reverses the commission without un-counting them; only a referral the owner refuses on review is left out. So a volume tier, once reached, is kept.\n\n### Caveats\n\n- **The sum can pass the cap on paper.** `commitment_points` and `volume_points` are the raw points; `commission_percent` is what is paid.\n- **A raise never re-prices a reward already written**: it changes what the next invoice of each earning referral pays. A drop re-prices every pending or approved commission at the lower rate, lowering only; a reward written at a rate below the new one keeps its amount, and nothing credited or paid out is touched.\n\n### Related events\n\n- `partner.referral_converted`: the rate copied onto one referral.\n- `partner.reward_earned`: what an invoice pays at that rate.",
                "summary": "The partner's commission rate moved, and the reason: a commitment was verified or lapsed, or their paying referrals reached a volume tier.",
                "tags": [
                    "partner.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "partner.rate_changed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `partner.rate_changed` here.",
                                        "enum": [
                                            "partner.rate_changed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "partner_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The partner's standing."
                                            },
                                            "previous_percent": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "decimal",
                                                "description": "The rate before, two decimal places; `null` when the partner had none stored yet."
                                            },
                                            "commission_percent": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "The rate now, two decimal places, the cap applied."
                                            },
                                            "reason": {
                                                "type": "string",
                                                "description": "What moved it.",
                                                "enum": [
                                                    "approved",
                                                    "commitment_verified",
                                                    "commitment_lapsed",
                                                    "volume_tier"
                                                ]
                                            },
                                            "commitment_points": {
                                                "type": "integer",
                                                "description": "Points from the commitments verified today."
                                            },
                                            "volume_points": {
                                                "type": "integer",
                                                "description": "Points from the volume tiers reached today."
                                            },
                                            "paying_referrals": {
                                                "type": "integer",
                                                "description": "How many of the partner's referrals have converted, the figure the tiers read."
                                            }
                                        },
                                        "required": [
                                            "partner_id",
                                            "previous_percent",
                                            "commission_percent",
                                            "reason",
                                            "commitment_points",
                                            "volume_points",
                                            "paying_referrals"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "partner.rate_changed",
                                        "created_at": "2026-12-03T16:40:12Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "partner_id": "2f6c1d0e-9a3b-4c5d-8e7f-6a5b4c3d2e1f",
                                            "previous_percent": "5.00",
                                            "commission_percent": "15.00",
                                            "reason": "commitment_verified",
                                            "commitment_points": 10,
                                            "volume_points": 0,
                                            "paying_referrals": 3
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-webhook-family": "partner"
            }
        },
        "copilot_credit.purchased": {
            "post": {
                "operationId": "webhook.copilot_credit.purchased",
                "description": "### When this fires\n\nStripe reported the payment for a pack: a Checkout session the creator completed, or an off-session charge the auto top-up made when the balance fell under their threshold. The paid amount becomes a grant that never lapses and the pack's bonus, when it carries one, a free grant beside it. One event per pack, however many Stripe events describe the payment.\n\n> **The bonus is free credit.** `bonus_cents` is granted by Subscriby, never charged by Stripe, and a refund of the pack takes it back.\n\n### Caveats\n\n- **Tax is not in `paid_cents`.** Stripe may have collected tax on top; the ledger is credited with the pack's price.\n- **A short payment credits nothing.** A payment under the pack's price is left pending and never announced.\n\n### Related events\n\n- `copilot_credit.refunded`: the pack's money going back.\n- `copilot_credit.low`: what the auto top-up answers.",
                "summary": "A pack of Copilot Credits was paid for and credited.",
                "tags": [
                    "copilot_credit.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "copilot_credit.purchased"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `copilot_credit.purchased` here.",
                                        "enum": [
                                            "copilot_credit.purchased"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "purchase_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The purchase, the id a later `copilot_credit.refunded` names."
                                            },
                                            "pack": {
                                                "type": "string",
                                                "description": "Which pack: `starter`, `regular`, `plus` or `max`."
                                            },
                                            "paid_cents": {
                                                "type": "integer",
                                                "description": "What the creator paid before tax, in cents, and what the paid grant started at."
                                            },
                                            "bonus_cents": {
                                                "type": "integer",
                                                "description": "The free credit granted beside it, in cents; `0` on the starter pack."
                                            },
                                            "currency": {
                                                "type": "string",
                                                "description": "`USD`."
                                            },
                                            "balance_cents": {
                                                "type": "integer",
                                                "description": "The whole balance after the purchase, free and paid together."
                                            }
                                        },
                                        "required": [
                                            "purchase_id",
                                            "pack",
                                            "paid_cents",
                                            "bonus_cents",
                                            "currency",
                                            "balance_cents"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "copilot_credit.purchased",
                                        "created_at": "2026-11-02T09:14:31Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "purchase_id": "0b1f7a2e-3c4d-4e5f-8a9b-1c2d3e4f5a6b",
                                            "pack": "regular",
                                            "paid_cents": 2500,
                                            "bonus_cents": 250,
                                            "currency": "USD",
                                            "balance_cents": 3250
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-webhook-family": "copilot_credit"
            }
        },
        "copilot_credit.granted": {
            "post": {
                "operationId": "webhook.copilot_credit.granted",
                "description": "### When this fires\n\nA new account received its welcome credit at registration, or Subscriby granted a promotion or goodwill by hand. The paid part and the bonus of a pack are not announced here; they are the purchase.\n\n### Caveats\n\n- **A lapsed grant is not announced.** The welcome credit's remainder simply stops counting at `expires_at`.\n\n### Related events\n\n- `copilot_credit.purchased`: the paid way in.",
                "summary": "Free Copilot Credits were granted to the creator.",
                "tags": [
                    "copilot_credit.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "copilot_credit.granted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `copilot_credit.granted` here.",
                                        "enum": [
                                            "copilot_credit.granted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "grant_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The grant."
                                            },
                                            "kind": {
                                                "type": "string",
                                                "description": "Why it was granted: `signup`, `promotion` or `goodwill`."
                                            },
                                            "cents": {
                                                "type": "integer",
                                                "description": "How much, in cents."
                                            },
                                            "expires_at": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "date-time",
                                                "description": "When it lapses; set on the welcome credit, `null` on a grant that never lapses."
                                            },
                                            "balance_cents": {
                                                "type": "integer",
                                                "description": "The whole balance after the grant, free and paid together."
                                            }
                                        },
                                        "required": [
                                            "grant_id",
                                            "kind",
                                            "cents",
                                            "expires_at",
                                            "balance_cents"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "copilot_credit.granted",
                                        "created_at": "2026-11-02T09:14:31Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "grant_id": "7c8d9e0f-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
                                            "kind": "signup",
                                            "cents": 500,
                                            "expires_at": "2027-01-31T09:14:31Z",
                                            "balance_cents": 500
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-webhook-family": "copilot_credit"
            }
        },
        "copilot_credit.low": {
            "post": {
                "operationId": "webhook.copilot_credit.low",
                "description": "### When this fires\n\nA unit of Copilot usage was drawn from the credit and left the balance under the threshold, and the creator had not been told in the last day. The same moment sends the creator a notice and, when their auto top-up is on, queues the charge for their pack.\n\n### Caveats\n\n- **Once a day at most.** A balance that stays low fires again only after a day; a purchase or a grant resets the clock.\n- **The free allowance does not count.** Units the plan includes draw nothing and never fire this.\n\n### Related events\n\n- `copilot_credit.purchased`: the top-up that follows.",
                "summary": "The creator's Copilot Credits fell under the low-balance threshold.",
                "tags": [
                    "copilot_credit.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "copilot_credit.low"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `copilot_credit.low` here.",
                                        "enum": [
                                            "copilot_credit.low"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "balance_cents": {
                                                "type": "integer",
                                                "description": "The whole balance at that moment, free and paid together."
                                            },
                                            "threshold_cents": {
                                                "type": "integer",
                                                "description": "The balance under which this event fires."
                                            }
                                        },
                                        "required": [
                                            "balance_cents",
                                            "threshold_cents"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "copilot_credit.low",
                                        "created_at": "2026-11-02T09:14:31Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "balance_cents": 420,
                                            "threshold_cents": 500
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-webhook-family": "copilot_credit"
            }
        },
        "copilot_credit.refunded": {
            "post": {
                "operationId": "webhook.copilot_credit.refunded",
                "description": "### When this fires\n\nA refund, partial or full, landed on the charge that paid for a pack. The refunded amount comes off the paid grant, past zero when the creator had already spent it; a refund that reaches the full price also takes the pack's bonus back. Stripe reports the refunded total cumulatively, so one event fires per refund with the running figure.\n\n### Caveats\n\n- **A negative balance closes the Copilot.** Nothing is invoiced for it; the next pack or grant covers it first.\n\n### Related events\n\n- `copilot_credit.purchased`: the pack that was refunded.",
                "summary": "Stripe refunded the charge for a pack and the credit was taken back.",
                "tags": [
                    "copilot_credit.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "copilot_credit.refunded"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `copilot_credit.refunded` here.",
                                        "enum": [
                                            "copilot_credit.refunded"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "purchase_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The purchase, as on `copilot_credit.purchased`."
                                            },
                                            "pack": {
                                                "type": "string",
                                                "description": "Which pack: `starter`, `regular`, `plus` or `max`."
                                            },
                                            "refunded_cents": {
                                                "type": "integer",
                                                "description": "Everything refunded on the purchase so far, in cents, this refund included."
                                            },
                                            "bonus_voided_cents": {
                                                "type": "integer",
                                                "description": "The bonus taken back by this refund, in cents; `0` until the refund reaches the full price."
                                            },
                                            "balance_cents": {
                                                "type": "integer",
                                                "description": "The whole balance after the refund; negative when the refunded credit had been spent."
                                            }
                                        },
                                        "required": [
                                            "purchase_id",
                                            "pack",
                                            "refunded_cents",
                                            "bonus_voided_cents",
                                            "balance_cents"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "copilot_credit.refunded",
                                        "created_at": "2026-11-05T16:02:10Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "purchase_id": "0b1f7a2e-3c4d-4e5f-8a9b-1c2d3e4f5a6b",
                                            "pack": "regular",
                                            "refunded_cents": 2500,
                                            "bonus_voided_cents": 250,
                                            "balance_cents": -180
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "account:read"
                ],
                "x-webhook-family": "copilot_credit"
            }
        },
        "knowledge.created": {
            "post": {
                "operationId": "webhook.knowledge.created",
                "description": "### When this fires\n\nA creator saved a question with its answer or a document on the Knowledge page, or an integration created one over the API or through `create_knowledge_entry`. The passages are in the index by the time the event fires, so a member can already be answered from a `members` entry.\n\n### Caveats\n\n- **A failed read still fires.** A document whose text could not be read is saved with `status: failed` and announced; the dashboard shows why, and the Copilot is handed nothing from it.\n\n### Related events\n\n- `knowledge.updated`: the entry's words or audience changing.\n- `knowledge.deleted`: the entry taken back.",
                "summary": "An entry was taught to the Copilot.",
                "tags": [
                    "knowledge.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "knowledge.created"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `knowledge.created` here.",
                                        "enum": [
                                            "knowledge.created"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "entry": {
                                                "type": "object",
                                                "description": "The entry: `id`, `kind` (`question` or `document`), `audience` (`members` or `team`), `status` (`ready`, `indexing` or `failed`), `title` and `chunk_count`, how many passages it became."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The project that taught it."
                                            }
                                        },
                                        "required": [
                                            "entry",
                                            "project_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "knowledge.created",
                                        "created_at": "2026-10-19T16:02:11Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "entry": {
                                                "id": "3b7e4d2a-9c1f-4a6b-8d5e-2f7c9a1b3e4d",
                                                "kind": "question",
                                                "audience": "members",
                                                "status": "ready",
                                                "title": "When does my membership renew?",
                                                "chunk_count": 1
                                            },
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-knowledge:view"
                ],
                "x-webhook-family": "knowledge"
            }
        },
        "knowledge.updated": {
            "post": {
                "operationId": "webhook.knowledge.updated",
                "description": "### When this fires\n\nA save moved the title, the audience or the words, from the dashboard, the API or `update_knowledge_entry`. A save that changed nothing fires nothing.\n\n### Caveats\n\n- **An audience change is the member boundary moving.** `members` to `team` means the Copilot stops answering members from the entry at once; the other way round, it starts.\n\n### Related events\n\n- `knowledge.created`: the entry's first save.",
                "summary": "An entry's title, audience or text changed.",
                "tags": [
                    "knowledge.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "knowledge.updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `knowledge.updated` here.",
                                        "enum": [
                                            "knowledge.updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "changes": {
                                                "type": "object",
                                                "description": "The named fields that moved, `title` and `audience`, each as `{from, to}`; empty when only the text changed."
                                            },
                                            "entry": {
                                                "type": "object",
                                                "description": "The entry after the change, as on `knowledge.created`."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The project."
                                            },
                                            "text_changed": {
                                                "type": "boolean",
                                                "description": "Whether the words changed; when they did, the passages were cut again and `entry.chunk_count` is the new count. The text itself never travels."
                                            }
                                        },
                                        "required": [
                                            "changes",
                                            "entry",
                                            "project_id",
                                            "text_changed"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "knowledge.updated",
                                        "created_at": "2026-10-19T16:40:08Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "changes": {
                                                "audience": {
                                                    "from": "members",
                                                    "to": "team"
                                                }
                                            },
                                            "entry": {
                                                "id": "3b7e4d2a-9c1f-4a6b-8d5e-2f7c9a1b3e4d",
                                                "kind": "question",
                                                "audience": "team",
                                                "status": "ready",
                                                "title": "When does my membership renew?",
                                                "chunk_count": 1
                                            },
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "text_changed": false
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-knowledge:view"
                ],
                "x-webhook-family": "knowledge"
            }
        },
        "knowledge.deleted": {
            "post": {
                "operationId": "webhook.knowledge.deleted",
                "description": "### When this fires\n\nA creator removed the entry on the Knowledge page, or an integration did over the API or through `delete_knowledge_entry`. The passages and the file are gone by the time the event fires.\n\n### Caveats\n\n- **Nothing is recoverable.** Deleting is not archiving: the words are gone with the passages. An integration that wants history keeps its own copy from `knowledge.created` and the API.\n\n### Related events\n\n- `knowledge.created`: how it began.",
                "summary": "An entry was taken back.",
                "tags": [
                    "knowledge.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "knowledge.deleted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `knowledge.deleted` here.",
                                        "enum": [
                                            "knowledge.deleted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "entry": {
                                                "type": "object",
                                                "description": "The entry as it was, in the shape `knowledge.created` carries."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The project."
                                            }
                                        },
                                        "required": [
                                            "entry",
                                            "project_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "knowledge.deleted",
                                        "created_at": "2026-10-19T17:12:45Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "entry": {
                                                "id": "3b7e4d2a-9c1f-4a6b-8d5e-2f7c9a1b3e4d",
                                                "kind": "question",
                                                "audience": "team",
                                                "status": "ready",
                                                "title": "When does my membership renew?",
                                                "chunk_count": 1
                                            },
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-knowledge:view"
                ],
                "x-webhook-family": "knowledge"
            }
        },
        "link.created": {
            "post": {
                "operationId": "webhook.link.created",
                "description": "### When this fires\n\nA creator authored a new Smart Link on the dashboard, over the REST API or via the `create_link` MCP tool. The link answers at `url` from this moment: a click counts, the visit waits in the visitor's browser for up to thirty days, and the member who signs in inside that window is attributed to the link.\n\nIt fires on **authoring**, not on the first click. A link created with an `expires_at` fires this immediately and stops counting when that instant passes; there is no separate event for the expiry.\n\n### Related events\n\n- `link.updated`: the link's fields changed.\n- `link.archived`: the link was put out of use.",
                "summary": "A new Smart Link was authored in a project.",
                "tags": [
                    "link.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "link.created"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `link.created` here.",
                                        "enum": [
                                            "link.created"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "link": {
                                                "type": "object",
                                                "description": "The link snapshot every `link.*` event carries.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The link's UUID. No prefix; only the envelope `id` is prefixed."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Creator-facing label. Never shown to members."
                                                    },
                                                    "slug": {
                                                        "type": "string",
                                                        "description": "The address segment after `/go/`: lowercase letters, digits and hyphens. The creator may rename it."
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "The stable code the attribution cookie and the bot's `via_` payload carry. **Never changes.**"
                                                    },
                                                    "destination": {
                                                        "type": "string",
                                                        "description": "Where the link sends people: the plan list, one plan's checkout, or the project's bot.",
                                                        "enum": [
                                                            "portal",
                                                            "plan",
                                                            "bot"
                                                        ]
                                                    },
                                                    "plan_id": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "uuid",
                                                        "description": "The plan a `plan` destination opens on; `null` for the other destinations."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "description": "The web address, `https://my.subscriby.net/{handle}/go/{slug}`. Rebuilt from the slug, so it moves when the slug does."
                                                    },
                                                    "expires_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When the link stops counting clicks. `null` means it runs until archived."
                                                    },
                                                    "archived_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When the creator put it out of use. Always `null` on this event."
                                                    },
                                                    "clicks_total": {
                                                        "type": "integer",
                                                        "description": "Lifetime clicks, counted once per address per link per hour. Always `0` on this event."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "slug",
                                                    "code",
                                                    "destination",
                                                    "plan_id",
                                                    "url",
                                                    "expires_at",
                                                    "archived_at",
                                                    "clicks_total"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "link"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "link.created",
                                        "created_at": "2026-11-20T09:14:02Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "link": {
                                                "id": "7c2e5a90-3f41-4b8d-9e62-1a0d4c8b7f35",
                                                "name": "YouTube description",
                                                "slug": "youtube",
                                                "code": "K7PMQ2X",
                                                "destination": "plan",
                                                "plan_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "url": "https://my.subscriby.net/jane/go/youtube",
                                                "expires_at": null,
                                                "archived_at": null,
                                                "clicks_total": 0
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-link:view"
                ],
                "x-webhook-family": "link"
            }
        },
        "link.updated": {
            "post": {
                "operationId": "webhook.link.updated",
                "description": "### When this fires\n\nA creator edited the link on the dashboard, over the REST API or via the `update_link` MCP tool, and at least one field of the snapshot moved. A save that changed nothing fires nothing.\n\n### Caveats\n\n- **A rename does not break what was shared.** The old `url` answers nothing after a rename, but the code in a printed QR or a bot deep link still attributes, because the cookie and the bot payload carry the code, never the slug.\n\n### Related events\n\n- `link.created`: the link was authored.\n- `link.archived`: the link was put out of use.",
                "summary": "A Smart Link's name, address, destination or expiry changed.",
                "tags": [
                    "link.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "link.updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `link.updated` here.",
                                        "enum": [
                                            "link.updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "link": {
                                                "type": "object",
                                                "description": "The link snapshot after the write; the same shape as on `link.created`.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The link's UUID."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Creator-facing label."
                                                    },
                                                    "slug": {
                                                        "type": "string",
                                                        "description": "The address segment as it stands now."
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "The stable code. Never among the changes."
                                                    },
                                                    "destination": {
                                                        "type": "string",
                                                        "description": "Where the link sends people now.",
                                                        "enum": [
                                                            "portal",
                                                            "plan",
                                                            "bot"
                                                        ]
                                                    },
                                                    "plan_id": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "uuid",
                                                        "description": "The plan a `plan` destination opens on; `null` for the other destinations."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "description": "The web address as it stands now."
                                                    },
                                                    "expires_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When the link stops counting clicks, or `null`."
                                                    },
                                                    "archived_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "Always `null` on this event; archiving fires `link.archived`."
                                                    },
                                                    "clicks_total": {
                                                        "type": "integer",
                                                        "description": "Lifetime clicks at the time of the write. Moves on its own and is never among the changes."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "slug",
                                                    "code",
                                                    "destination",
                                                    "plan_id",
                                                    "url",
                                                    "expires_at",
                                                    "archived_at",
                                                    "clicks_total"
                                                ]
                                            },
                                            "changes": {
                                                "type": "object",
                                                "description": "One entry per snapshot key whose value moved, keyed by field name, each `{ \"from\": …, \"to\": … }`. A rename moves `slug` and `url`.",
                                                "additionalProperties": {
                                                    "type": "object",
                                                    "properties": {
                                                        "from": {
                                                            "description": "The previous value, in its original type."
                                                        },
                                                        "to": {
                                                            "description": "The new value, in its original type."
                                                        }
                                                    },
                                                    "required": [
                                                        "from",
                                                        "to"
                                                    ]
                                                }
                                            }
                                        },
                                        "required": [
                                            "link",
                                            "changes"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "link.updated",
                                        "created_at": "2026-11-21T10:02:40Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "link": {
                                                "id": "7c2e5a90-3f41-4b8d-9e62-1a0d4c8b7f35",
                                                "name": "YouTube description",
                                                "slug": "youtube",
                                                "code": "K7PMQ2X",
                                                "destination": "plan",
                                                "plan_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "url": "https://my.subscriby.net/jane/go/youtube",
                                                "expires_at": null,
                                                "archived_at": null,
                                                "clicks_total": 48
                                            },
                                            "changes": {
                                                "slug": {
                                                    "from": "yt",
                                                    "to": "youtube"
                                                },
                                                "url": {
                                                    "from": "https://my.subscriby.net/jane/go/yt",
                                                    "to": "https://my.subscriby.net/jane/go/youtube"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-link:view"
                ],
                "x-webhook-family": "link"
            }
        },
        "link.archived": {
            "post": {
                "operationId": "webhook.link.archived",
                "description": "### When this fires\n\nA creator archived the link on the dashboard, over the REST API (`DELETE`) or via the `archive_link` MCP tool. Archiving is the only removal a link has: its row, the members it brought and the money they paid all stay, so the funnel keeps adding up. From this moment its address lands on the portal home without counting, and a visit still waiting in a browser is attributed to it when that visitor signs in. Archiving a link already archived fires nothing.\n\n### Related events\n\n- `link.created`: the link was authored.\n- `link.updated`: the link's fields changed.",
                "summary": "A Smart Link was put out of use.",
                "tags": [
                    "link.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "link.archived"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `link.archived` here.",
                                        "enum": [
                                            "link.archived"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "link": {
                                                "type": "object",
                                                "description": "The link's final snapshot; the same shape as on `link.created`.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The link's UUID."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Creator-facing label."
                                                    },
                                                    "slug": {
                                                        "type": "string",
                                                        "description": "The address segment the link answered at."
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "The stable code, still attributing a visit that was waiting when the link was archived."
                                                    },
                                                    "destination": {
                                                        "type": "string",
                                                        "description": "Where the link sent people.",
                                                        "enum": [
                                                            "portal",
                                                            "plan",
                                                            "bot"
                                                        ]
                                                    },
                                                    "plan_id": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "uuid",
                                                        "description": "The plan a `plan` destination opened on; `null` for the other destinations."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "description": "The web address, which now lands on the portal home without counting."
                                                    },
                                                    "expires_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When the link would have stopped on its own, or `null`."
                                                    },
                                                    "archived_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When it was put out of use. Set on this event."
                                                    },
                                                    "clicks_total": {
                                                        "type": "integer",
                                                        "description": "The lifetime figure the link keeps."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "slug",
                                                    "code",
                                                    "destination",
                                                    "plan_id",
                                                    "url",
                                                    "expires_at",
                                                    "archived_at",
                                                    "clicks_total"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "link"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "link.archived",
                                        "created_at": "2026-12-01T08:30:11Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "link": {
                                                "id": "7c2e5a90-3f41-4b8d-9e62-1a0d4c8b7f35",
                                                "name": "YouTube description",
                                                "slug": "youtube",
                                                "code": "K7PMQ2X",
                                                "destination": "plan",
                                                "plan_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "url": "https://my.subscriby.net/jane/go/youtube",
                                                "expires_at": null,
                                                "archived_at": "2026-12-01T08:30:11+00:00",
                                                "clicks_total": 1204
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-link:view"
                ],
                "x-webhook-family": "link"
            }
        },
        "subscription.created": {
            "post": {
                "operationId": "webhook.subscription.created",
                "description": "### When this fires\n\nExactly two paths emit this event:\n\n- **Access-code redemption**: a subscriber redeems a code against a plan.\n- **Cardless trial start**: a subscriber begins a trial that took no payment method.\n\nBoth are zero-payment acquisitions. Every paid acquisition (every payment provider, both recurring subscriptions and one-time passes) emits `subscription.activated` instead, and never emits `subscription.created`.\n\n> This event does **not** fire for paid checkouts. A card, wallet, or crypto purchase emits `subscription.activated` instead. If you are building access control for a paying audience, subscribe to both.\n\nThe `data` keys differ by path. Absent keys are **omitted entirely**, not sent as `null`.\n\n> `access_code` carries the complete code. It is already consumed and cannot be redeemed again, but treat it as you would any other customer identifier and avoid logging it into systems you do not control.\n\n### Caveats\n\n- Do not treat this as the universal \"a subscription exists\" signal. For paid projects it never fires. The reliable pattern is to subscribe to both `subscription.created` and `subscription.activated` and de-duplicate on `data.subscription_id`.\n- The access-code path also emits `access_code.redeemed` and either `member.joined` or `member.trial_joined` for the same subscription.\n- The cardless-trial path also emits `subscription.trial_started` and `member.trial_joined`.\n- The `POST /v1/webhook-endpoints/{endpoint}/test` endpoint sends a synthetic `subscription.created` payload regardless of your project's payment configuration. A successful test does not prove this event will fire in production.\n\n### Related events\n\n- `subscription.activated`: the paid-checkout equivalent.\n- `access_code.redeemed`: fires alongside on the access-code path.\n- `subscription.trial_started`: fires alongside on the cardless-trial path.",
                "summary": "New subscription created via access-code redemption or cardless trial.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.created"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.created` here.",
                                        "enum": [
                                            "subscription.created"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Access-code path only. Duplicates the envelope `project_id`."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The subscriber's project-scoped user id."
                                            },
                                            "trial_ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Cardless-trial path only. Absent on the access-code path."
                                            },
                                            "access_code": {
                                                "type": "string",
                                                "description": "Access-code path only. The **full redeemed code**, not masked. Absent on the trial path."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload-access-code-redemption": {
                                    "summary": "access-code redemption",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.created",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "access_code": "SLATE-SUNDAY-4F2A9"
                                        }
                                    }
                                },
                                "payload-cardless-trial-start": {
                                    "summary": "cardless trial start",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.created",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "trial_ends_at": "2026-05-25T10:05:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.activated": {
            "post": {
                "operationId": "webhook.subscription.activated",
                "description": "### When this fires\n\nOn the **first successful payment** for a subscription, across every payment provider: Stripe, PayPal, Paystack, Razorpay, Skrill, CeyPay, and CoinPayments. It covers both recurring subscriptions and one-time (non-recurring) passes.\n\nIt fires **once per subscription**, at acquisition. It is not a general \"became active\" signal:\n\n| Transition                              | Event actually emitted       |\n| --------------------------------------- | ---------------------------- |\n| First paid checkout                     | `subscription.activated`     |\n| Recurring renewal charge                | `subscription.renewed`       |\n| Paused → resumed                        | `subscription.unpaused`      |\n| Cancelled → reinstated before `ends_at` | `subscription.reactivated`   |\n| Past-due → collected                    | `subscription.renewed`       |\n| Trial → paying                          | `member.converted`           |\n| Access code / cardless trial            | `subscription.created`       |\n\nA Stripe subscription that begins in a trial still emits `subscription.activated` at acquisition, because the provider creates the subscription at that moment. The later trial-to-paid transition emits `member.converted` only.\n\n> This is the paid-acquisition event. If you only subscribe to one subscription event for a paying audience, subscribe to this one, not `subscription.created`, which never fires for paid checkouts.\n\n`data.provider` is never `access_code` on this event; code redemptions emit `subscription.created` instead.\n\n### Caveats\n\n- **Once per subscription.** Stripe and PayPal de-duplicate with a persistent guard key; the remaining providers emit only on the non-renewal branch of their payment handler. Renewals never re-emit it.\n- To capture _every_ acquisition path (paid, comped code, and cardless trial) subscribe to both `subscription.activated` and `subscription.created`, then de-duplicate on `data.subscription_id`.\n- Paid acquisitions do **not** emit `member.joined`. That event is access-code-only. Use `subscription.activated` as the paid-audience join signal.\n- `payment.succeeded` fires for the same charge and carries the amount, currency, and external payment id, which this event does not.\n- The `POST /v1/webhook-endpoints/{endpoint}/test` endpoint sends a synthetic `subscription.created` payload, never `subscription.activated`. Testing an endpoint does not exercise this event.\n\n### Related events\n\n- `subscription.created`: the zero-payment acquisition equivalent.\n- `payment.succeeded`: the charge behind this activation.\n- `subscription.renewed`: every subsequent cycle.\n- `member.converted`: trial-to-paying transition.",
                "summary": "A paid subscription is acquired. Fires once, at first activation.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.activated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.activated` here.",
                                        "enum": [
                                            "subscription.activated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "provider": {
                                                "type": "string",
                                                "description": "The provider that took the first payment. Never `access_code` on this event.",
                                                "enum": [
                                                    "stripe",
                                                    "paypal",
                                                    "paystack",
                                                    "razorpay",
                                                    "skrill",
                                                    "ceypay",
                                                    "coinpayments"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "provider"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.activated",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "provider": "stripe"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.trial_started": {
            "post": {
                "operationId": "webhook.subscription.trial_started",
                "description": "### When this fires\n\nA subscriber starts a trial on a trial-enabled plan. Three paths emit it: a cardless trial, an access-code redemption against a trial plan, or a **Stripe** checkout that begins in a trial window.\n\nTrial checkouts through the other providers (PayPal, Paystack, Razorpay, Skrill, CeyPay, CoinPayments) do not currently emit this event; only Stripe reports the trialing status transition back to Subscriby.\n\n> Pairs with `member.trial_joined`: both fire together when a subscriber starts a trial on the cardless-trial and access-code paths.\n\nThe `data` keys differ by path. Absent keys are **omitted entirely**, not sent as `null`.\n\n### Caveats\n\n- On the cardless-trial and access-code paths this is paired with `subscription.created` and `member.trial_joined` for the same `subscription_id`. On the Stripe path it is paired with `subscription.activated` instead, and no `member.*` join event fires.\n- Plans with `trial_days = 0` skip this event entirely.\n\n### Related events\n\n- `subscription.trial_converting`: fires 24h before `trial_ends_at`.\n- `subscription.trial_expired`: fires if no conversion occurs.",
                "summary": "Trial-enabled plan starts free window.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.trial_started"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.trial_started` here.",
                                        "enum": [
                                            "subscription.trial_started"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the trial is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "trial_ends_at": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "date-time",
                                                "description": "Present on every path. May be `null` on the Stripe path when the subscription row has no `trial_ends_at` recorded yet; fall back to [the subscription endpoint](https://docs.subscriby.net/api/v1/reference/subscriptions)."
                                            },
                                            "access_code": {
                                                "type": "string",
                                                "description": "Access-code path only. The full redeemed code."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Access-code path only. Mirrors the envelope `project_id`."
                                            },
                                            "provider": {
                                                "type": "string",
                                                "description": "Stripe path only. Always `stripe`."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "trial_ends_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload-cardless-trial-or-access-code-redemption": {
                                    "summary": "cardless trial or access-code redemption",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.trial_started",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "trial_ends_at": "2026-05-25T10:05:00Z"
                                        }
                                    }
                                },
                                "payload-stripe-checkout-starting-in-a-trial": {
                                    "summary": "Stripe checkout starting in a trial",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.trial_started",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "trial_ends_at": "2026-05-25T10:05:00Z",
                                            "provider": "stripe"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.trial_converting": {
            "post": {
                "operationId": "webhook.subscription.trial_converting",
                "description": "### When this fires\n\nFires 24 hours before `trial_ends_at` to give consumers a window to send conversion-reminder messaging. Emitted once per trial, by the hourly trial-conversion notifier.\n\n> Fires exactly once per trial, 24 hours before `trial_ends_at`.\n\n### Caveats\n\n- Idempotency is enforced server-side: each trial receives this event at most once.\n- If `trial_ends_at` is moved closer than 24h after the trial has already started, the notice may not fire.\n\n### Related events\n\n- `subscription.trial_started`: predecessor.\n- `subscription.activated`, `member.converted`: fire on successful conversion.\n- `subscription.trial_expired`: alternative path if conversion fails.",
                "summary": "Trial about to convert. Fires 24h before `trial_ends_at`.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.trial_converting"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.trial_converting` here.",
                                        "enum": [
                                            "subscription.trial_converting"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the trial is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "trial_ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the trial window ends."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "trial_ends_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.trial_converting",
                                        "created_at": "2026-05-24T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "trial_ends_at": "2026-05-25T10:05:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.trial_expired": {
            "post": {
                "operationId": "webhook.subscription.trial_expired",
                "description": "### When this fires\n\nA trial ends without conversion. Emitted alongside `subscription.expired` for the same subscription.\n\n### Caveats\n\n- Successful conversions fire `subscription.activated` and `member.converted` instead.\n- Expect `subscription.expired` and `member.churned` to follow for the same subscriber.\n\n### Related events\n\n- `subscription.trial_started`: predecessor.\n- `subscription.expired`: fires alongside.",
                "summary": "Trial ended without conversion.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.trial_expired"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.trial_expired` here.",
                                        "enum": [
                                            "subscription.trial_expired"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the trial was on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "trial_ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the trial window ended."
                                            },
                                            "ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Subscription end timestamp; matches `trial_ends_at` for cardless trials."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "trial_ends_at",
                                            "ends_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.trial_expired",
                                        "created_at": "2026-05-25T10:06:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "trial_ends_at": "2026-05-25T10:05:00Z",
                                            "ends_at": "2026-05-25T10:05:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.renewed": {
            "post": {
                "operationId": "webhook.subscription.renewed",
                "description": "### When this fires\n\nRecurring billing successfully charges the subscriber and the subscription is renewed for another period.\n\n### Caveats\n\n- A `subscription.renewed` is always paired with a `payment.succeeded` for the same charge.\n- Currency may differ from the plan's nominal currency for providers that auto-convert at the gateway.\n\n### Related events\n\n- `payment.succeeded`: paired payment event.\n- `subscription.past_due`, `subscription.unpaid`: failure paths.",
                "summary": "Recurring billing successfully charged the subscriber.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.renewed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.renewed` here.",
                                        "enum": [
                                            "subscription.renewed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "provider": {
                                                "type": "string",
                                                "description": "Payment provider slug."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "Charged amount in major units of `currency`, formatted as a string."
                                            },
                                            "currency": {
                                                "type": "string",
                                                "description": "ISO 4217 currency code."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "provider",
                                            "amount",
                                            "currency"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.renewed",
                                        "created_at": "2026-06-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "provider": "stripe",
                                            "amount": "29.00",
                                            "currency": "USD"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.reactivated": {
            "post": {
                "operationId": "webhook.subscription.reactivated",
                "description": "### When this fires\n\nA previously cancelled subscription is reactivated before its `ends_at`. The subscription returns to the active state and the next billing cycle resumes.\n\n### Caveats\n\n- Reactivation is only possible while `ends_at` is in the future. After expiration, a new subscription must be created instead.\n- Pairs with a renewed provider subscription for paid plans; the next charge will follow normal cadence.\n\n### Related events\n\n- `subscription.cancelled`: predecessor.\n- `subscription.expired`: alternative path if reactivation does not occur.",
                "summary": "Cancelled subscription re-activated before `ends_at`.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.reactivated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.reactivated` here.",
                                        "enum": [
                                            "subscription.reactivated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Refreshed period-end timestamp."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "ends_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.reactivated",
                                        "created_at": "2026-05-22T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "ends_at": "2026-06-18T10:05:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.paused": {
            "post": {
                "operationId": "webhook.subscription.paused",
                "description": "### When this fires\n\nA creator suspended a member's **access**. `payment_status` becomes `paused`, `paused_at` is stamped, and the member is removed from every linked resource.\n\n> **This is an access pause, not a billing pause.** The member's payment provider keeps charging them on schedule. Subscriby does not pause collection, suspend the PayPal agreement, or otherwise hold the charge. If you need billing to stop, cancel instead.\n>\n> The split is deliberate: Subscriby settles through seven providers and only some can hold a recurring charge at all, so a pause meaning \"stop billing\" would work on some providers and silently not on others. Access is something Subscriby controls directly, so it behaves identically everywhere.\n\nBefore 1 September 2026 this event fired without anything happening: no provider was called _and_ no access was removed. If you built on the old behaviour, note that a paused member now genuinely loses access.\n\n### Caveats\n\n- Pausing does not change `ends_at`, and does not stop the clock. The member is still being billed, so a long pause costs them money for access they do not have. Tell them, or cancel instead.\n- Access removal is queued, one call per linked resource, so it completes shortly after this event rather than atomically with it.\n- Pausing does not detach resources, so no `member.resource_removed` events follow. Revocation happens only on expiry or cancellation.\n\n### Related events\n\n- `subscription.unpaused`: paired transition.",
                "summary": "A member's access was suspended. Billing is unaffected and continues on schedule.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.paused"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.paused` here.",
                                        "enum": [
                                            "subscription.paused"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "paused_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the pause took effect."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "paused_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.paused",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "paused_at": "2026-05-18T10:05:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.unpaused": {
            "post": {
                "operationId": "webhook.subscription.unpaused",
                "description": "### When this fires\n\nA suspended member has their access restored, with **fresh** invite links: an invite link revoked on pause cannot be un-revoked.\n\nBilling is not mentioned here because it never stopped: pausing suspends access only, so there is nothing on the provider side to resume.\n\n### Caveats\n\n- Expect `member.resource_added` entries as resources are re-attached. `subscription.activated` does **not** follow an unpause; it fires only once, at first paid acquisition.\n- Renewal cadence resumes from the original `ends_at` boundary, not the unpause moment.\n\n### Related events\n\n- `subscription.paused`: paired transition.\n- `member.resource_added`: re-grant signal.",
                "summary": "Paused subscription resumes; resource invite links re-issued.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.unpaused"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.unpaused` here.",
                                        "enum": [
                                            "subscription.unpaused"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "resumed_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the pause was lifted."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "resumed_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.unpaused",
                                        "created_at": "2026-05-22T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "resumed_at": "2026-05-22T10:05:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.past_due": {
            "post": {
                "operationId": "webhook.subscription.past_due",
                "description": "### When this fires\n\nA scheduled charge fails but the subscription remains within its grace window. The platform will continue to attempt collection.\n\nCoverage is partial: only **Stripe** and **Razorpay** report the past-due transition back to Subscriby. Failed renewals on PayPal, Paystack, Skrill, CeyPay, and CoinPayments emit `payment.failed` without a matching `subscription.past_due`, so treat `payment.failed` as the reliable cross-provider signal.\n\n### Caveats\n\n- Pairs with a `payment.failed` event for the underlying charge.\n- If retries succeed, `subscription.renewed` follows. If grace expires, `subscription.unpaid` fires instead.\n\n### Related events\n\n- `payment.failed`: paired payment event.\n- `subscription.unpaid`: grace-window terminal state.",
                "summary": "Billing fails but grace period is active.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.past_due"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.past_due` here.",
                                        "enum": [
                                            "subscription.past_due"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "provider": {
                                                "type": "string",
                                                "description": "Payment provider slug."
                                            },
                                            "external_payment_id": {
                                                "type": "string",
                                                "description": "Razorpay path only; absent on the Stripe path. Provider charge id for the failed attempt; useful for support escalation."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "provider"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.past_due",
                                        "created_at": "2026-06-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "provider": "razorpay",
                                            "external_payment_id": "pay_NxYz.."
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.unpaid": {
            "post": {
                "operationId": "webhook.subscription.unpaid",
                "description": "### When this fires\n\nA subscription's grace period ends without successful collection. The provider has given up retrying. Resource access is typically revoked shortly after.\n\nThis event is emitted for **Stripe only**; it depends on the provider reporting an `unpaid` subscription status. On every other provider, an abandoned subscription surfaces as `subscription.expired` once `ends_at` passes, with no preceding `subscription.unpaid`.\n\n### Caveats\n\n- After this event, the subscription is non-recoverable on its current terms; the subscriber must restart with a new subscription.\n- Expect `subscription.expired` and `member.churned` to follow.\n\n### Related events\n\n- `subscription.past_due`: predecessor inside the grace window.\n- `subscription.expired`: terminal state.",
                "summary": "Billing permanently failed; grace expired.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.unpaid"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.unpaid` here.",
                                        "enum": [
                                            "subscription.unpaid"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "provider": {
                                                "type": "string",
                                                "description": "Payment provider slug."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "provider"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.unpaid",
                                        "created_at": "2026-07-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "provider": "stripe"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.cancelled": {
            "post": {
                "operationId": "webhook.subscription.cancelled",
                "description": "### When this fires\n\nCancellation is recorded by the subscriber, by the creator, or by the payment provider (a gateway-side cancellation, or a terminal payment failure on CeyPay, CoinPayments or Skrill). If the paid period still has time left, the subscription stays active and the subscriber keeps access until `ends_at`, after which `subscription.expired` fires. If no paid period remains, `ends_at` is set to the cancellation moment and resource access is revoked straight away.\n\n### Caveats\n\n- Cancellation is reversible until `ends_at`; see `subscription.reactivated`.\n- A renewal does not occur after cancellation; `subscription.renewed` will not fire.\n\n### Related events\n\n- `subscription.expired`: fires when the period ends.\n- `subscription.reactivated`: reverse path.",
                "summary": "Cancellation recorded; access continues until `ends_at`.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.cancelled"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.cancelled` here.",
                                        "enum": [
                                            "subscription.cancelled"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "provider": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Payment provider key: a gateway slug (`stripe`, `paypal`, `skrill`, `coinpayments`, `paystack`, `razorpay`, `ceypay`, `accesscode`) or a `connector:provider` key for a currency a connector brings (`telegram:stars`; `platformcurrency` is the legacy alias earlier native rows carried). `null` when the subscription has no payment method attached."
                                            },
                                            "reason": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "CeyPay, CoinPayments and Skrill only. The provider failure reason that triggered the cancellation. `null` when the provider reported none. Absent on every other provider and on creator/subscriber-initiated cancellations."
                                            },
                                            "paypal_event": {
                                                "type": "string",
                                                "description": "PayPal path only. The raw PayPal event type behind the cancellation: `BILLING.SUBSCRIPTION.CANCELLED` or `BILLING.SUBSCRIPTION.EXPIRED`."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "provider"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.cancelled",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "provider": "stripe"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.expired": {
            "post": {
                "operationId": "webhook.subscription.expired",
                "description": "### When this fires\n\nThe subscription's `ends_at` has passed. Resource access is revoked and the subscription transitions to its terminal state.\n\n### Caveats\n\n- Pairs with `member.churned` when this is the subscriber's last active subscription.\n- Resource access is revoked as part of expiry; expect `member.resource_removed` events for each granted resource.\n\n### Related events\n\n- `subscription.cancelled`, `subscription.unpaid`, `subscription.trial_expired`: predecessors.\n- `member.churned`: paired member-level event.",
                "summary": "`ends_at` reached; access revoked.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.expired"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.expired` here.",
                                        "enum": [
                                            "subscription.expired"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription was on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the subscription was due to end."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "ends_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.expired",
                                        "created_at": "2026-06-18T10:06:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "ends_at": "2026-06-18T10:05:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.refunded": {
            "post": {
                "operationId": "webhook.subscription.refunded",
                "description": "### When this fires\n\nA **full** subscription-level refund settles. The subscription is always expired as a result: resource access is revoked and `subscription.expired` (plus `member.churned` when this was the subscriber's last active subscription) follows for the same subscription.\n\n> Fires only for a **settled** refund. A refund a provider has queued but not yet paid out raises nothing; access is never revoked for money that has not actually moved.\n\n### Caveats\n\n- Emitted by Stripe, PayPal, Paystack, Razorpay and Skrill. CoinPayments and CeyPay expose no refund notification, so a refund taken there is invisible to this event.\n- A **partial** refund raises `payment.refunded` only. This event means the whole charge came back, and access is revoked with it.\n- Skrill reports a chargeback rather than a merchant refund, and only if the creator's Skrill account is configured to post one.\n- Subscriby expires the subscription itself on a full refund; it does not wait for the provider's own cancellation to arrive.\n- For per-payment refunds (no subscription mutation), see `payment.refunded`.\n\n### Related events\n\n- `payment.refunded`: payment-level analogue.\n- `subscription.cancelled`: often paired in practice.",
                "summary": "Refund recorded against a subscription.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.refunded"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.refunded` here.",
                                        "enum": [
                                            "subscription.refunded"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "Refunded amount in major units, formatted as a string. The currency is not on this event; resolve it with [the subscription endpoint](https://docs.subscriby.net/api/v1/reference/subscriptions)."
                                            },
                                            "full_refund": {
                                                "type": "boolean",
                                                "description": "Always `true` on this event: a partial refund emits `payment.refunded` only, where this field can be `false`."
                                            },
                                            "external_payment_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Provider-side id of the payment that was refunded, as the provider reported it. `null` when the provider supplied none."
                                            },
                                            "reason": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Reason code from the provider; absent when not supplied."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "amount",
                                            "full_refund",
                                            "external_payment_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.refunded",
                                        "created_at": "2026-05-20T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "amount": "29.00",
                                            "full_refund": true,
                                            "external_payment_id": "pi_3Nxy..",
                                            "reason": "requested_by_customer"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.upgraded": {
            "post": {
                "operationId": "webhook.subscription.upgraded",
                "description": "### When this fires\n\nA subscriber is switched to a higher-priced plan on the same project. The plan assignment, currency, and stored price on the Subscriby subscription record are updated, and this event reports the move.\n\nThe switch does not itself perform a provider-side pro-ration or issue a charge. Any billing adjustment is whatever the provider does on the next cycle.\n\n### Caveats\n\n- Direction is decided by comparing the two plan prices, normalised to USD, at switch time. Only a strictly higher new price emits `subscription.upgraded`; an **equal-price switch emits `subscription.downgraded`**, which is worth guarding for if you offer same-price plan swaps.\n- Trial windows do not carry across switches; if the destination plan has a trial it does not start.\n\n### Related events\n\n- `subscription.downgraded`: opposite direction.\n- `payment.succeeded`: the next successful charge on the new plan.",
                "summary": "Subscriber moved to a higher-priced plan.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.upgraded"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.upgraded` here.",
                                        "enum": [
                                            "subscription.upgraded"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "from_plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan id the subscription was on prior to the change."
                                            },
                                            "to_plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan id the subscription is now on."
                                            },
                                            "proration_amount": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "decimal",
                                                "description": "Reserved. **Always `null`**: pro-ration is not yet computed for this event."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "from_plan_id",
                                            "to_plan_id",
                                            "proration_amount"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.upgraded",
                                        "created_at": "2026-05-22T10:05:00Z",
                                        "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",
                                            "from_plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "to_plan_id": "e07b4a29-51c6-4d83-9f10-2b8ac635d174",
                                            "proration_amount": null
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.downgraded": {
            "post": {
                "operationId": "webhook.subscription.downgraded",
                "description": "### When this fires\n\nA subscriber is switched to a lower-priced plan on the same project. The plan assignment, currency, and stored price on the Subscriby subscription record are updated, and this event reports the move.\n\nThe switch does not itself perform a provider-side pro-ration or issue a credit. Any billing adjustment is whatever the provider does on the next cycle.\n\n### Caveats\n\n- No credit or refund is issued by this action. If you owe subscribers a mid-cycle credit on downgrade, apply it yourself through the provider.\n- Direction is decided by comparing the two plan prices, normalised to USD. Anything that is not strictly more expensive lands here, so a **switch between two equally-priced plans emits this event**, not `subscription.upgraded`.\n- Resource access tied to the higher tier may be revoked on the next renewal cycle.\n\n### Related events\n\n- `subscription.upgraded`: opposite direction.\n- `member.resource_removed`: emitted when premium-tier resources are detached.",
                "summary": "Subscriber moved to a lower-priced plan.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.downgraded"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.downgraded` here.",
                                        "enum": [
                                            "subscription.downgraded"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "from_plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan id the subscription was on prior to the change."
                                            },
                                            "to_plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan id the subscription is now on."
                                            },
                                            "proration_amount": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "decimal",
                                                "description": "Reserved. **Always `null`**: pro-ration is not yet computed for this event."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "from_plan_id",
                                            "to_plan_id",
                                            "proration_amount"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.downgraded",
                                        "created_at": "2026-05-22T10:05:00Z",
                                        "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",
                                            "from_plan_id": "e07b4a29-51c6-4d83-9f10-2b8ac635d174",
                                            "to_plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "proration_amount": null
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.payment_recovered": {
            "post": {
                "operationId": "webhook.subscription.payment_recovered",
                "description": "### When this fires\n\nA renewal that had failed is paid: the rail's next charge settles, or the rail reports the subscription active again before the money reaches the ledger. Either closes the clock Revenue Recovery opened at the failure, converts every notice sent during the window and stamps `recovered_at`. When the window had already closed and access had been paused, the member's invite links are reissued and they are welcomed back, which `subscription.access_restored` reports separately.\n\nOnly a renewal of a membership that has paid before opens a clock, so this never fires for a first purchase or for a one-time rail. A charge that settles on a subscription with no open clock fires `subscription.renewed` alone.\n\n### Related events\n\n- `subscription.access_suspended`: the pause this may be undoing.\n- `subscription.access_restored`: the reissued links, when `access_restored` is `true`.\n- `payment.succeeded`: the charge behind it.",
                "summary": "A failed renewal was settled, and the grace clock on the subscription closed.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.payment_recovered"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.payment_recovered` here.",
                                        "enum": [
                                            "subscription.payment_recovered"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The plan the subscription is on."
                                            },
                                            "provider": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The rail the renewal settled on; `null` when the subscription's payment method is gone.",
                                                "enum": [
                                                    "stripe",
                                                    "paypal",
                                                    "skrill",
                                                    "coinpayments",
                                                    "paystack",
                                                    "razorpay",
                                                    "ceypay",
                                                    null
                                                ]
                                            },
                                            "payment_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The settled payment that closed the clock, or `null` when the rail's status closed it before the money landed; the payment is attached when it does."
                                            },
                                            "access_restored": {
                                                "type": "boolean",
                                                "description": "`true` when the window had closed and access had been paused, so the member's links were reissued."
                                            },
                                            "recovered_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the clock closed."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "provider",
                                            "payment_id",
                                            "access_restored",
                                            "recovered_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.payment_recovered",
                                        "created_at": "2026-10-14T10:00:00Z",
                                        "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",
                                            "provider": "stripe",
                                            "payment_id": "f8e1c3a5-2d7b-4e96-b0c4-9a5d3f7e1b28",
                                            "access_restored": true,
                                            "recovered_at": "2026-10-14T10:00:00+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.access_suspended": {
            "post": {
                "operationId": "webhook.subscription.access_suspended",
                "description": "### When this fires\n\nThe grace window the project gives a failed renewal (0 to 30 days, set per project; a new project starts at 0, which pauses at the failure itself) ran out with no settled charge. The member is removed from the project's resources and told that their access is paused and how to pay, the subscription stays `past_due` so the rail's own retries can still settle it, and the next settled charge brings them back. A window of zero days pauses at the failure itself.\n\nA membership that never paid is revoked at the failure without a window, as it always was, and fires `subscription.expired` instead.\n\n### Caveats\n\n- The subscription's status does not change on this event: it was already `past_due`, and stays so until a charge settles or the rail gives up (`subscription.unpaid`).\n- A creator's own pause (`subscription.paused`) is a different thing and never collides with this: a subscription the creator paused is left out of the grace sweep.\n\n### Related events\n\n- `subscription.past_due`: the failure that opened the window.\n- `subscription.payment_recovered`: the charge that ends it.\n- `subscription.access_restored`: the member let back in.",
                "summary": "A failed renewal's grace window closed unpaid, and the member's access was paused.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.access_suspended"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.access_suspended` here.",
                                        "enum": [
                                            "subscription.access_suspended"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The plan the subscription is on."
                                            },
                                            "payment_failed_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the renewal first failed and the clock opened."
                                            },
                                            "grace_days": {
                                                "type": "integer",
                                                "description": "The project's grace window in days at the time of the failure."
                                            },
                                            "grace_ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the window closed."
                                            },
                                            "suspended_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When access was paused: the first hourly sweep after the window closed."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "payment_failed_at",
                                            "grace_days",
                                            "grace_ends_at",
                                            "suspended_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.access_suspended",
                                        "created_at": "2026-10-19T10:30:00Z",
                                        "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",
                                            "payment_failed_at": "2026-10-12T10:00:00+00:00",
                                            "grace_days": 7,
                                            "grace_ends_at": "2026-10-19T10:00:00+00:00",
                                            "suspended_at": "2026-10-19T10:30:00+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.access_restored": {
            "post": {
                "operationId": "webhook.subscription.access_restored",
                "description": "### When this fires\n\nA charge settled, or the rail reported the subscription active, for a member whose access had been paused at the close of a grace window. Their bearer links are revoked and reissued, they are welcomed back, and the clock is cleared. It fires beside `subscription.payment_recovered`, which carries the payment; this one carries the pause it undid.\n\n### Related events\n\n- `subscription.access_suspended`: the pause.\n- `subscription.payment_recovered`: the charge, raised beside this.\n- `member.resource_added`: the resources the member rejoins.",
                "summary": "A member whose access was paused for non-payment was let back in.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.access_restored"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.access_restored` here.",
                                        "enum": [
                                            "subscription.access_restored"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The plan the subscription is on."
                                            },
                                            "suspended_at": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "date-time",
                                                "description": "When access had been paused; `null` only if the pause left no stamp."
                                            },
                                            "restored_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the member was let back in."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "suspended_at",
                                            "restored_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.access_restored",
                                        "created_at": "2026-10-21T08:15:00Z",
                                        "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",
                                            "suspended_at": "2026-10-19T10:30:00+00:00",
                                            "restored_at": "2026-10-21T08:15:00+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.cancellation_feedback": {
            "post": {
                "operationId": "webhook.subscription.cancellation_feedback",
                "description": "### When this fires\n\nA member reached the cancellation screen, on the portal or in a connector chat, and answered the question the project asks on the way out: a reason from the fixed list and, if they wrote one, a sentence of their own. It fires the moment the reason is recorded, before the member sees the offer or confirms, so a member who then takes the offer and stays still appears here. The creator is alerted at the same time. A project that switched the question off asks nothing and fires nothing; its offers are still counted, through `subscription.offer_taken` and the cancellation records.\n\n### Related events\n\n- `subscription.offer_taken`: the member took the offer instead of cancelling.\n- `subscription.cancelled`: the member went on and cancelled.",
                "summary": "A cancelling member said why they are leaving.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.cancellation_feedback"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.cancellation_feedback` here.",
                                        "enum": [
                                            "subscription.cancellation_feedback"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "cancellation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The cancellation record, carried by `subscription.offer_taken` when the member takes the offer."
                                            },
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "reason": {
                                                "type": "string",
                                                "description": "The reason the member picked from the fixed list.",
                                                "enum": [
                                                    "too_expensive",
                                                    "not_using_enough",
                                                    "not_enough_content",
                                                    "content_not_expected",
                                                    "found_another_community",
                                                    "not_the_right_fit",
                                                    "taking_a_break",
                                                    "got_what_i_needed",
                                                    "technical_problems",
                                                    "signed_up_by_mistake",
                                                    "other"
                                                ]
                                            },
                                            "feedback": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The sentence the member added, up to 500 characters, or `null` when they skipped it."
                                            },
                                            "offer_shown": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The offer the member sees next, or `null` when the owner's plan or the member's rail allows none.",
                                                "enum": [
                                                    "pause",
                                                    "discount",
                                                    "return_coupon",
                                                    null
                                                ]
                                            },
                                            "surface": {
                                                "type": "string",
                                                "description": "Where the member answered: the portal, or a connector chat.",
                                                "enum": [
                                                    "portal",
                                                    "bot"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "cancellation_id",
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "reason",
                                            "feedback",
                                            "offer_shown",
                                            "surface"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.cancellation_feedback",
                                        "created_at": "2026-10-22T09:30:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "cancellation_id": "9d2c6b71-3e48-4f0a-a5d7-1b8e4c9f2a36",
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "reason": "too_expensive",
                                            "feedback": "Money is tight this quarter.",
                                            "offer_shown": "pause",
                                            "surface": "portal"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "subscription.offer_taken": {
            "post": {
                "operationId": "webhook.subscription.offer_taken",
                "description": "### When this fires\n\nA member on the cancellation screen accepted the one offer the project makes for their rail: a pause for one billing cycle where the rail can hold the charge (Stripe, PayPal), a discount on the renewals where the rail can carry a coupon (Stripe), or a coupon to come back with everywhere else. A pause holds the charge at the gateway and pauses access, and the hourly sweep lets the member back in when `resumes_at` passes; a discount is minted once at the gateway and applied to the subscription; a return coupon is handed to the member on the screen and in a chat message, and the cancellation goes on. The offer is re-derived when the member accepts, so a stale screen cannot claim an offer the project no longer makes.\n\n### Caveats\n\n- A pause taken here keeps the subscription: it reads as `paused` until `resumes_at`, and no `subscription.cancelled` follows. A return coupon does not: the cancellation goes on and `subscription.cancelled` fires as usual.\n- A member sees one offer per cancellation. Declining it fires nothing; the shown offer is still counted on the cancellation record.\n\n### Related events\n\n- `subscription.cancellation_feedback`: the reason recorded just before.\n- `subscription.paused` / `subscription.unpaused`: the pause's two ends.\n- `coupon.redeemed`: a return coupon used at checkout.",
                "summary": "A cancelling member took the offer the cancellation screen made.",
                "tags": [
                    "subscription.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "subscription.offer_taken"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `subscription.offer_taken` here.",
                                        "enum": [
                                            "subscription.offer_taken"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "cancellation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The cancellation record, the same one `subscription.cancellation_feedback` named when the project asked a reason."
                                            },
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "offer": {
                                                "type": "string",
                                                "description": "Which offer was taken.",
                                                "enum": [
                                                    "pause",
                                                    "discount",
                                                    "return_coupon"
                                                ]
                                            },
                                            "coupon_code": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The coupon code applied to the renewals (`discount`) or handed to the member (`return_coupon`); `null` for a pause."
                                            },
                                            "resumes_at": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "date-time",
                                                "description": "When a pause ends and the member is let back in; `null` for the other offers."
                                            }
                                        },
                                        "required": [
                                            "cancellation_id",
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "offer",
                                            "coupon_code",
                                            "resumes_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "subscription.offer_taken",
                                        "created_at": "2026-10-22T09:31:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "cancellation_id": "9d2c6b71-3e48-4f0a-a5d7-1b8e4c9f2a36",
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "offer": "pause",
                                            "coupon_code": null,
                                            "resumes_at": "2026-11-22T09:31:00+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "subscription"
            }
        },
        "sequence.created": {
            "post": {
                "operationId": "webhook.sequence.created",
                "description": "### When this fires\n\nA creator built a sequence on the Revenue Recovery page: a name, a trigger and whether it runs. It fires on **authoring**, with no steps yet; the steps arrive one by one as `sequence.updated`. Nobody is enrolled by this event: enrolment waits for the trigger to fire for a member, and a sequence with no steps enrols nobody even then.\n\n### Related events\n\n- `sequence.updated`: the steps arrive, and every later change.\n- `sequence.enrolled`: the first member enters it.",
                "summary": "A recovery sequence was built in a project.",
                "tags": [
                    "sequence.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "sequence.created"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `sequence.created` here.",
                                        "enum": [
                                            "sequence.created"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "sequence": {
                                                "type": "object",
                                                "description": "The sequence snapshot every lifecycle event carries.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The sequence's UUID. No prefix; only the envelope `id` is prefixed."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Creator-facing label, up to 120 characters. Never shown to members."
                                                    },
                                                    "trigger": {
                                                        "type": "string",
                                                        "description": "What enrols a member. Only `churned` can be chosen today.",
                                                        "enum": [
                                                            "churned",
                                                            "lead",
                                                            "stalled_checkout",
                                                            "trial_ending"
                                                        ]
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Whether the sequence enrols and sends. `true` unless the creator switched it off at authoring."
                                                    },
                                                    "steps": {
                                                        "type": "array",
                                                        "description": "The steps in order. Always empty on this event.",
                                                        "items": {
                                                            "type": "object"
                                                        }
                                                    },
                                                    "steps[]": {
                                                        "type": "object",
                                                        "description": "One step of the sequence.",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "format": "uuid",
                                                                "description": "The step's UUID."
                                                            },
                                                            "position": {
                                                                "type": "integer",
                                                                "description": "The step's place, contiguous from 1."
                                                            },
                                                            "delay_days": {
                                                                "type": "integer",
                                                                "description": "Days after the trigger for the first step (0 to 180; 0 is the next hourly run), after the step before for the rest (1 to 180)."
                                                            },
                                                            "coupon_id": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "format": "uuid",
                                                                "description": "The project coupon the step carries, or `null`."
                                                            }
                                                        },
                                                        "required": [
                                                            "id",
                                                            "position",
                                                            "delay_days",
                                                            "coupon_id"
                                                        ]
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the sequence was built."
                                                    },
                                                    "updated_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When it last changed."
                                                    },
                                                    "deleted_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "When the creator deleted it. Always `null` on this event."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "trigger",
                                                    "active",
                                                    "steps",
                                                    "steps[]",
                                                    "created_at",
                                                    "updated_at",
                                                    "deleted_at"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "sequence"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "sequence.created",
                                        "created_at": "2026-10-22T09:30:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "sequence": {
                                                "id": "3e9a7c21-5d84-4f06-b2c1-8a7e5d4f9b02",
                                                "name": "Win-back after churn",
                                                "trigger": "churned",
                                                "active": true,
                                                "steps": [],
                                                "created_at": "2026-10-22T09:30:00+00:00",
                                                "updated_at": "2026-10-22T09:30:00+00:00",
                                                "deleted_at": null
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-sequence:view"
                ],
                "x-webhook-family": "sequence"
            }
        },
        "sequence.updated": {
            "post": {
                "operationId": "webhook.sequence.updated",
                "description": "### When this fires\n\nA creator renamed the sequence, moved it to another trigger, switched it on or off, or added, rewrote or removed a step on the Revenue Recovery page. Every save fires it, so a consumer always holds the snapshot after the latest write. Switching a sequence off also lets every member part-way through it go, each as `sequence.exited` with the reason `disabled`, and enrols nobody new until it runs again.\n\n### Caveats\n\n- **Positions move, enrolments do not.** A member who was due the removed step receives the step that took its place, and a member past the last remaining step completes on the next sweep. Read the steps by id if you track one.\n- A sequence may hold up to 8 steps. The ninth is refused on the dashboard and fires nothing.\n\n### Related events\n\n- `sequence.created`: the sequence was built.\n- `sequence.exited`: the members let go when the sequence was switched off.\n- `sequence.deleted`: the sequence was deleted.",
                "summary": "A recovery sequence changed.",
                "tags": [
                    "sequence.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "sequence.updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `sequence.updated` here.",
                                        "enum": [
                                            "sequence.updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "sequence": {
                                                "type": "object",
                                                "description": "The sequence snapshot after the write; the same shape as on `sequence.created`.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The sequence's UUID."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Creator-facing label as it stands now."
                                                    },
                                                    "trigger": {
                                                        "type": "string",
                                                        "description": "What enrols a member now.",
                                                        "enum": [
                                                            "churned",
                                                            "lead",
                                                            "stalled_checkout",
                                                            "trial_ending"
                                                        ]
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Whether the sequence enrols and sends now. `false` after it was switched off."
                                                    },
                                                    "steps": {
                                                        "type": "array",
                                                        "description": "The steps in order after the write.",
                                                        "items": {
                                                            "type": "object"
                                                        }
                                                    },
                                                    "steps[]": {
                                                        "type": "object",
                                                        "description": "One step of the sequence.",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "format": "uuid",
                                                                "description": "The step's UUID. A rewritten step keeps its id; a removed one is gone from the list."
                                                            },
                                                            "position": {
                                                                "type": "integer",
                                                                "description": "The step's place, contiguous from 1. Removing a step moves the ones after it up."
                                                            },
                                                            "delay_days": {
                                                                "type": "integer",
                                                                "description": "Days after the trigger for the first step (0 to 180; 0 is the next hourly run), after the step before for the rest (1 to 180)."
                                                            },
                                                            "coupon_id": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "format": "uuid",
                                                                "description": "The project coupon the step carries, or `null`."
                                                            }
                                                        },
                                                        "required": [
                                                            "id",
                                                            "position",
                                                            "delay_days",
                                                            "coupon_id"
                                                        ]
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the sequence was built."
                                                    },
                                                    "updated_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When this write landed."
                                                    },
                                                    "deleted_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time",
                                                        "description": "Always `null` on this event; deleting fires `sequence.deleted`."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "trigger",
                                                    "active",
                                                    "steps",
                                                    "steps[]",
                                                    "created_at",
                                                    "updated_at",
                                                    "deleted_at"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "sequence"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "sequence.updated",
                                        "created_at": "2026-10-22T09:45:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "sequence": {
                                                "id": "3e9a7c21-5d84-4f06-b2c1-8a7e5d4f9b02",
                                                "name": "Win-back after churn",
                                                "trigger": "churned",
                                                "active": true,
                                                "steps": [
                                                    {
                                                        "id": "6b1f3d58-9c2a-4e7d-a0f4-2d8c7b5e1a93",
                                                        "position": 1,
                                                        "delay_days": 3,
                                                        "coupon_id": null
                                                    },
                                                    {
                                                        "id": "9d4e2a07-1b6c-4f58-8e3a-5c7f0d2b9e41",
                                                        "position": 2,
                                                        "delay_days": 7,
                                                        "coupon_id": "c2d8e4f1-7a3b-4c9d-b5e6-1f0a9d8c7b65"
                                                    }
                                                ],
                                                "created_at": "2026-10-22T09:30:00+00:00",
                                                "updated_at": "2026-10-22T09:45:00+00:00",
                                                "deleted_at": null
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-sequence:view"
                ],
                "x-webhook-family": "sequence"
            }
        },
        "sequence.deleted": {
            "post": {
                "operationId": "webhook.sequence.deleted",
                "description": "### When this fires\n\nA creator deleted the sequence on the Revenue Recovery page. Every member part-way through it is let go first, each as `sequence.exited` with the reason `deleted`, and only then does this fire with the final snapshot. The row is kept out of sight with its history: the messages already sent stay in the project's activity ledger and still count as converted when the member pays again.\n\n### Related events\n\n- `sequence.exited`: the members let go, with the reason `deleted`, just before this.\n- `sequence.updated`: the sequence's earlier changes.",
                "summary": "A recovery sequence was deleted.",
                "tags": [
                    "sequence.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "sequence.deleted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `sequence.deleted` here.",
                                        "enum": [
                                            "sequence.deleted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "sequence": {
                                                "type": "object",
                                                "description": "The sequence's final snapshot; the same shape as on `sequence.created`.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The sequence's UUID."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Creator-facing label."
                                                    },
                                                    "trigger": {
                                                        "type": "string",
                                                        "description": "What enrolled its members.",
                                                        "enum": [
                                                            "churned",
                                                            "lead",
                                                            "stalled_checkout",
                                                            "trial_ending"
                                                        ]
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "Whether it was running when deleted. The deletion itself stops it either way."
                                                    },
                                                    "steps": {
                                                        "type": "array",
                                                        "description": "The steps it held, in order.",
                                                        "items": {
                                                            "type": "object"
                                                        }
                                                    },
                                                    "steps[]": {
                                                        "type": "object",
                                                        "description": "One step of the sequence.",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "format": "uuid",
                                                                "description": "The step's UUID."
                                                            },
                                                            "position": {
                                                                "type": "integer",
                                                                "description": "The step's place, contiguous from 1."
                                                            },
                                                            "delay_days": {
                                                                "type": "integer",
                                                                "description": "Days after the trigger for the first step, after the step before for the rest."
                                                            },
                                                            "coupon_id": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "format": "uuid",
                                                                "description": "The project coupon the step carried, or `null`."
                                                            }
                                                        },
                                                        "required": [
                                                            "id",
                                                            "position",
                                                            "delay_days",
                                                            "coupon_id"
                                                        ]
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the sequence was built."
                                                    },
                                                    "updated_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When it last changed, the deletion included."
                                                    },
                                                    "deleted_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When it was deleted. Set on this event."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "name",
                                                    "trigger",
                                                    "active",
                                                    "steps",
                                                    "steps[]",
                                                    "created_at",
                                                    "updated_at",
                                                    "deleted_at"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "sequence"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "sequence.deleted",
                                        "created_at": "2026-11-02T14:10:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "sequence": {
                                                "id": "3e9a7c21-5d84-4f06-b2c1-8a7e5d4f9b02",
                                                "name": "Win-back after churn",
                                                "trigger": "churned",
                                                "active": true,
                                                "steps": [
                                                    {
                                                        "id": "6b1f3d58-9c2a-4e7d-a0f4-2d8c7b5e1a93",
                                                        "position": 1,
                                                        "delay_days": 3,
                                                        "coupon_id": null
                                                    },
                                                    {
                                                        "id": "9d4e2a07-1b6c-4f58-8e3a-5c7f0d2b9e41",
                                                        "position": 2,
                                                        "delay_days": 7,
                                                        "coupon_id": "c2d8e4f1-7a3b-4c9d-b5e6-1f0a9d8c7b65"
                                                    }
                                                ],
                                                "created_at": "2026-10-22T09:30:00+00:00",
                                                "updated_at": "2026-11-02T14:10:00+00:00",
                                                "deleted_at": "2026-11-02T14:10:00+00:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-sequence:view"
                ],
                "x-webhook-family": "sequence"
            }
        },
        "sequence.enrolled": {
            "post": {
                "operationId": "webhook.sequence.enrolled",
                "description": "### When this fires\n\nThe sequence's trigger fired for a member of the project and nothing stood in the way. For `churned` that is `member.churned`: the member's last live membership ended, through its end date, a cancellation that ran out or the close of a failed-payment grace window. For `lead` it is `member.lead_created`; for `stalled_checkout` the hourly sweep's `checkout.stalled`; for `trial_ending` the hourly trial sweep, once a trial without a card is within the project's lead time of its end. The member is enrolled into every running sequence on that trigger, once each, provided the sequence has at least one step, the member holds nothing the trigger counts as a conversion (any live membership, or for `trial_ending` a paid one), they have not asked the project's sequences to stop, they are not already part-way through that sequence, and the project owner's plan includes sequences. `next_due_at` is the moment of the trigger plus the first step's delay; the step goes out on the first hourly sweep after it.\n\n### Caveats\n\n- A member who buys again before the first step is due never receives it: the sweep finds them holding a live membership and ends the passage as `sequence.converted` instead.\n- A sequence switched off between the trigger and the first step lets the member go as `sequence.exited` with the reason `disabled`.\n\n### Related events\n\n- `member.churned`: the churn trigger.\n- `sequence.step_sent`: the steps that follow.\n- `sequence.converted`: how a passage ends well.\n- `sequence.exited`: how a passage ends otherwise.",
                "summary": "A member entered a recovery sequence.",
                "tags": [
                    "sequence.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "sequence.enrolled"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `sequence.enrolled` here.",
                                        "enum": [
                                            "sequence.enrolled"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "enrollment_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The passage's identifier, carried by every later event of this member in this sequence."
                                            },
                                            "sequence_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The sequence entered."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member's project-scoped user id."
                                            },
                                            "subscription_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The membership whose end fired the trigger, or `null` when the trigger named none."
                                            },
                                            "plan_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The plan the passage is about and every step's button opens: the stalled checkout's, the trial's or the churned membership's; `null` when the trigger carried none."
                                            },
                                            "trigger": {
                                                "type": "string",
                                                "description": "What fired.",
                                                "enum": [
                                                    "churned",
                                                    "lead",
                                                    "stalled_checkout",
                                                    "trial_ending"
                                                ]
                                            },
                                            "next_due_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the first step falls due. The hourly sweep sends it on its first run after this moment."
                                            }
                                        },
                                        "required": [
                                            "enrollment_id",
                                            "sequence_id",
                                            "subscriber_id",
                                            "subscription_id",
                                            "plan_id",
                                            "trigger",
                                            "next_due_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "sequence.enrolled",
                                        "created_at": "2026-10-25T08:00:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "enrollment_id": "a4c7e912-3b5d-4f80-9e16-7d2a8c5b4f03",
                                            "sequence_id": "3e9a7c21-5d84-4f06-b2c1-8a7e5d4f9b02",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
                                            "trigger": "churned",
                                            "next_due_at": "2026-10-28T08:00:00+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-sequence:view"
                ],
                "x-webhook-family": "sequence"
            }
        },
        "sequence.step_sent": {
            "post": {
                "operationId": "webhook.sequence.step_sent",
                "description": "### When this fires\n\nThe hourly sweep found the step due and the member's connected account took the message: the creator's text with the placeholders filled for this member, the way back to the project as a button, and the step's coupon code in the text where the creator placed it. The message goes out as an announcement, so the member's channel choices and opt-outs apply. A platform that refuses for the moment (a rate limit, a passing fault, a misconfigured installation) fires nothing and the step stays due for the next hour; one that refuses for good, or a member with no account to reach, fires nothing and ends the passage as `sequence.exited` with the reason `opted_out`. After the last step the passage completes quietly: no event marks completion.\n\n### Related events\n\n- `sequence.enrolled`: the passage this step belongs to.\n- `sequence.converted`: the member paid again after reading it.\n- `coupon.redeemed`: the step's coupon used at checkout.",
                "summary": "One step of a recovery sequence reached a member.",
                "tags": [
                    "sequence.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "sequence.step_sent"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `sequence.step_sent` here.",
                                        "enum": [
                                            "sequence.step_sent"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "enrollment_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The passage this step belongs to, as on `sequence.enrolled`."
                                            },
                                            "sequence_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The sequence."
                                            },
                                            "step_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The step that went out."
                                            },
                                            "position": {
                                                "type": "integer",
                                                "description": "The step's place in the sequence at the time it went out."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member's project-scoped user id."
                                            },
                                            "coupon_code": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The code of the coupon the step carried, or `null` for a step without one."
                                            },
                                            "sent_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the message was delivered."
                                            }
                                        },
                                        "required": [
                                            "enrollment_id",
                                            "sequence_id",
                                            "step_id",
                                            "position",
                                            "subscriber_id",
                                            "coupon_code",
                                            "sent_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "sequence.step_sent",
                                        "created_at": "2026-10-28T08:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "enrollment_id": "a4c7e912-3b5d-4f80-9e16-7d2a8c5b4f03",
                                            "sequence_id": "3e9a7c21-5d84-4f06-b2c1-8a7e5d4f9b02",
                                            "step_id": "6b1f3d58-9c2a-4e7d-a0f4-2d8c7b5e1a93",
                                            "position": 1,
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "coupon_code": null,
                                            "sent_at": "2026-10-28T08:05:00+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-sequence:view"
                ],
                "x-webhook-family": "sequence"
            }
        },
        "sequence.converted": {
            "post": {
                "operationId": "webhook.sequence.converted",
                "description": "### When this fires\n\nA charge settled for the member in the project while they were part-way through one or more sequences, or the sweep found them holding a live membership again before a charge reached the ledger. Every open passage of theirs in the project ends as won back: the steps they received since enrolling are counted as converted by that payment, the creator is alerted, and this fires once per passage. The win is credited to the sequence whether or not the member used the coupon a step carried.\n\n### Related events\n\n- `payment.succeeded`: the charge behind it.\n- `subscription.activated`: the membership the member bought back.\n- `sequence.exited`: every other way a passage ends.",
                "summary": "A member in a recovery sequence paid again.",
                "tags": [
                    "sequence.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "sequence.converted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `sequence.converted` here.",
                                        "enum": [
                                            "sequence.converted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "enrollment_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The passage that ended as a win."
                                            },
                                            "sequence_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The sequence."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member's project-scoped user id."
                                            },
                                            "payment_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The settled payment that closed the passage, or `null` when the sweep found the member live again before a charge was recorded."
                                            },
                                            "converted_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the passage ended."
                                            }
                                        },
                                        "required": [
                                            "enrollment_id",
                                            "sequence_id",
                                            "subscriber_id",
                                            "payment_id",
                                            "converted_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "sequence.converted",
                                        "created_at": "2026-11-01T17:20:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "enrollment_id": "a4c7e912-3b5d-4f80-9e16-7d2a8c5b4f03",
                                            "sequence_id": "3e9a7c21-5d84-4f06-b2c1-8a7e5d4f9b02",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "payment_id": "f8e1c3a5-2d7b-4e96-b0c4-9a5d3f7e1b28",
                                            "converted_at": "2026-11-01T17:20:00+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-sequence:view"
                ],
                "x-webhook-family": "sequence"
            }
        },
        "sequence.exited": {
            "post": {
                "operationId": "webhook.sequence.exited",
                "description": "### When this fires\n\nA passage ended for a reason other than the member paying again: the creator switched the sequence off (`disabled`) or deleted it (`deleted`), or the member could not be reached on any connected account and the platform refused for good (`opted_out`). It fires once per passage. A passage that ran through every step completes without an event, and one that ended because the member paid again fires `sequence.converted` instead.\n\n### Related events\n\n- `sequence.updated`: the switch-off behind a `disabled` exit.\n- `sequence.deleted`: the deletion behind a `deleted` exit.\n- `sequence.converted`: the one ending that is not an exit.",
                "summary": "A member left a recovery sequence before its last step.",
                "tags": [
                    "sequence.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "sequence.exited"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `sequence.exited` here.",
                                        "enum": [
                                            "sequence.exited"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "enrollment_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The passage that ended."
                                            },
                                            "sequence_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The sequence."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member's project-scoped user id."
                                            },
                                            "reason": {
                                                "type": "string",
                                                "description": "Why: the sequence was switched off, the sequence was deleted, or the member could not be reached.",
                                                "enum": [
                                                    "disabled",
                                                    "deleted",
                                                    "opted_out"
                                                ]
                                            },
                                            "exited_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the passage ended."
                                            }
                                        },
                                        "required": [
                                            "enrollment_id",
                                            "sequence_id",
                                            "subscriber_id",
                                            "reason",
                                            "exited_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "sequence.exited",
                                        "created_at": "2026-11-02T14:10:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "enrollment_id": "a4c7e912-3b5d-4f80-9e16-7d2a8c5b4f03",
                                            "sequence_id": "3e9a7c21-5d84-4f06-b2c1-8a7e5d4f9b02",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "reason": "disabled",
                                            "exited_at": "2026-11-02T14:10:00+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-sequence:view"
                ],
                "x-webhook-family": "sequence"
            }
        },
        "payment.succeeded": {
            "post": {
                "operationId": "webhook.payment.succeeded",
                "description": "### When this fires\n\nA payment provider confirms a successful charge against a subscriber. Fires for both initial checkouts and recurring renewals.\n\n### Caveats\n\n- For first-time paid checkouts, `subscription.activated` is the matching subscription-level event, not `subscription.created`, which never fires for paid purchases.\n- Renewals pair `payment.succeeded` with `subscription.renewed`.\n- Card numbers, PAN, and CVV are never included in payloads.\n\n### Related events\n\n- `subscription.activated` (first payment), `subscription.renewed` (renewals): paired subscription events.\n- `payment.failed`: alternative outcome.",
                "summary": "A provider confirms a successful charge.",
                "tags": [
                    "payment.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "payment.succeeded"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `payment.succeeded` here.",
                                        "enum": [
                                            "payment.succeeded"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "provider": {
                                                "type": "string",
                                                "description": "Provider slug."
                                            },
                                            "external_payment_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Provider charge / invoice / transaction id. `null` when the provider's success payload carried none."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "Charged amount in major units of `currency`, formatted as a string."
                                            },
                                            "currency": {
                                                "type": "string",
                                                "description": "ISO 4217 currency code."
                                            },
                                            "billing_reason": {
                                                "type": "string",
                                                "description": "Always present. Subscriby derives `subscription_create` (first successful payment) or `subscription_cycle` (renewal) from the subscription's payment history; for Stripe, the invoice's own `billing_reason` is passed through when present, so values such as `subscription_update` or `manual` can also appear."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "provider",
                                            "external_payment_id",
                                            "amount",
                                            "currency",
                                            "billing_reason"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "payment.succeeded",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "provider": "stripe",
                                            "external_payment_id": "pi_3Nxy..",
                                            "amount": "29.00",
                                            "currency": "USD",
                                            "billing_reason": "subscription_create"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "payment"
            }
        },
        "payment.failed": {
            "post": {
                "operationId": "webhook.payment.failed",
                "description": "### When this fires\n\nA payment provider rejects a charge: invalid card, insufficient funds, gateway risk, expired source. Emitted by Stripe, CeyPay, CoinPayments, Paystack, Razorpay and Skrill. PayPal does not emit `payment.failed`; a failed PayPal charge surfaces only through the subscription-level events.\n\n### Caveats\n\n- The paired subscription event differs by provider: Razorpay emits `subscription.past_due` alongside; CeyPay, CoinPayments and Skrill instead cancel the subscription and emit `subscription.cancelled`; Paystack emits nothing alongside; for Stripe, `subscription.past_due` arrives separately when Stripe next syncs the subscription's status. Do not assume a subscription event accompanies every `payment.failed`.\n- A single billing cycle can produce multiple `payment.failed` events as the provider retries.\n\n### Related events\n\n- `payment.succeeded`: alternative outcome.\n- `subscription.past_due`: paired subscription event for recurring failures.",
                "summary": "A provider rejects a charge.",
                "tags": [
                    "payment.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "payment.failed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `payment.failed` here.",
                                        "enum": [
                                            "payment.failed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription identifier."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "provider": {
                                                "type": "string",
                                                "description": "Provider slug."
                                            },
                                            "external_payment_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Provider charge id when one was created; `null` for pre-charge rejections."
                                            },
                                            "reason": {
                                                "type": "string",
                                                "description": "Human-readable rejection reason, mostly free text from the provider (Razorpay sends the fixed slug `razorpay_halted`, Stripe falls back to `stripe_invoice_failed`). Not a stable enum: do not branch on its exact value."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "**Stripe only.** Attempted amount in major units, as a decimal string. Omitted entirely by the other providers, never sent as `null`."
                                            },
                                            "currency": {
                                                "type": "string",
                                                "description": "**Stripe only.** Uppercase ISO 4217 code. Omitted entirely by the other providers, never sent as `null`."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "provider",
                                            "external_payment_id",
                                            "reason"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "payment.failed",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "provider": "stripe",
                                            "external_payment_id": "pi_3Nxy..",
                                            "reason": "Your card was declined.",
                                            "amount": "29.00",
                                            "currency": "USD"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "payment"
            }
        },
        "payment.pending": {
            "post": {
                "operationId": "webhook.payment.pending",
                "description": "### When this fires\n\nA subscriber initiates checkout and is redirected to the provider, but the charge is not yet confirmed (bank transfer, crypto settlement, hosted-checkout sessions).\n\nPayPal carries **neither** `session_id` nor `order_id`: a PayPal `payment.pending` gives you only `provider`, `plan_id`, and `subscriber_id`, so it cannot be correlated to a specific checkout attempt. Absent keys are omitted entirely rather than sent as `null`; the one exception is Stripe's `session_id`, which is always present on the Stripe path but may be `null`.\n\n### Caveats\n\n- A pending payment is not yet a subscription. `subscription_id` is intentionally absent.\n- The same checkout may emit one `payment.pending` followed by either `payment.succeeded` or `payment.failed`. Correlate on `session_id` or `order_id` where the provider supplies one; for PayPal, fall back to `subscriber_id` plus `plan_id`.\n- Subscribers who close the provider page without completing will not produce a final outcome event; pending sessions can hang indefinitely.\n\n### Related events\n\n- `payment.succeeded`, `payment.failed`: terminal outcomes.\n- `subscription.activated`: fires alongside the `payment.succeeded` that completes a first checkout.",
                "summary": "A payment is initiated, awaiting provider confirmation.",
                "tags": [
                    "payment.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "payment.pending"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `payment.pending` here.",
                                        "enum": [
                                            "payment.pending"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "provider": {
                                                "type": "string",
                                                "description": "Provider slug."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan being purchased."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "session_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "**Stripe only.** Checkout session id; defensively `null` if the created session carried no id. Absent (not `null`) for all other providers."
                                            },
                                            "order_id": {
                                                "type": "string",
                                                "description": "Paystack, Razorpay, Skrill, CeyPay, CoinPayments. Absent for Stripe."
                                            }
                                        },
                                        "required": [
                                            "provider",
                                            "plan_id",
                                            "subscriber_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "payment.pending",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "provider": "stripe",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "session_id": "cs_test_.."
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "payment"
            }
        },
        "payment.refunded": {
            "post": {
                "operationId": "webhook.payment.refunded",
                "description": "### When this fires\n\nA per-payment refund settles. Pairs with `subscription.refunded` when the refund covers the entire subscription.\n\n> **Settled refunds only.** A refund a provider has queued but not yet paid out raises nothing; access is never revoked for money that has not actually moved.\n\n### Caveats\n\n- Emitted by Stripe, PayPal, Paystack, Razorpay and Skrill. CoinPayments and CeyPay expose no refund notification.\n- Raised for partial refunds as well as full ones. Read `full_refund` to tell them apart; a partial refund leaves the subscription and its access untouched.\n- Stripe reports a running total across refunds; the `amount` here is **this** refund, not the cumulative figure.\n- Distinct from `subscription.refunded`, which represents the subscription's reaction. A refund may emit only `payment.refunded` if the subscription itself is unaffected.\n- Partial refunds are represented by `amount` being less than the original charge.\n\n### Related events\n\n- `payment.succeeded`: predecessor.\n- `subscription.refunded`: subscription-level analogue.",
                "summary": "A specific charge is refunded, fully or partially.",
                "tags": [
                    "payment.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "payment.refunded"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `payment.refunded` here.",
                                        "enum": [
                                            "payment.refunded"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription the original payment belonged to."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription was on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "external_payment_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Provider charge id that was refunded. `null` when the provider's refund payload carried no originating charge id (Razorpay)."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "Refunded amount in major units of the subscription's currency, as a decimal string. The currency itself is not carried on this event; resolve it from the plan or from the preceding `payment.succeeded`."
                                            },
                                            "full_refund": {
                                                "type": "boolean",
                                                "description": "`true` when the refund unwinds the whole charge. A full refund additionally emits `subscription.refunded` and immediately revokes access; a partial one does not."
                                            },
                                            "reason": {
                                                "type": "string",
                                                "description": "Provider-supplied refund reason, or `chargeback` for reversals. Omitted entirely when the provider supplied none, never sent as `null`."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "external_payment_id",
                                            "amount",
                                            "full_refund"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "payment.refunded",
                                        "created_at": "2026-05-20T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "external_payment_id": "pi_3Nxy..",
                                            "amount": "29.00",
                                            "full_refund": true
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "payment"
            }
        },
        "checkout.stalled": {
            "post": {
                "operationId": "webhook.checkout.stalled",
                "description": "### When this fires\n\nThe hourly sweep found a checkout started more than the project's window ago (`checkout_stall_hours`, 1 hour by default) with no charge settled for the member and no live membership held, and had not counted a stall for that member in the last day. The row is stamped, the event goes out, and the member enters every running sequence on the `stalled_checkout` trigger with the plan they were buying, so the step's button reopens that plan; `enrollment_id` names the first passage opened, or is `null` when the project runs no such sequence.\n\n### Caveats\n\n- A member who starts a checkout three times inside a day stalls once; the two later rows are stamped without an event.\n- A stall says nothing about why. Stripe's session may have expired, the member may have changed their mind, or the gateway may have refused the card; the ledger only knows no charge settled.\n\n### Related events\n\n- `payment.pending`: the start of the checkout.\n- `sequence.enrolled`: the passage the stall opened.\n- `checkout.recovered`: how it ends well.",
                "summary": "A checkout stayed open past the project's window.",
                "tags": [
                    "checkout.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "checkout.stalled"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `checkout.stalled` here.",
                                        "enum": [
                                            "checkout.stalled"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "checkout_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The ledger row, carried by `checkout.recovered` when the member comes back."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member's project-scoped user id."
                                            },
                                            "plan_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The plan they were buying; `null` once the plan is deleted."
                                            },
                                            "provider": {
                                                "type": "string",
                                                "description": "The rail the checkout opened on, as the payment methods are keyed."
                                            },
                                            "surface": {
                                                "type": "string",
                                                "description": "Where the member started.",
                                                "enum": [
                                                    "portal",
                                                    "bot"
                                                ]
                                            },
                                            "started_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the gateway's page was handed over."
                                            },
                                            "stalled_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the sweep counted it."
                                            },
                                            "enrollment_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The first stalled-checkout passage opened for the member, or `null`."
                                            }
                                        },
                                        "required": [
                                            "checkout_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "provider",
                                            "surface",
                                            "started_at",
                                            "stalled_at",
                                            "enrollment_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "checkout.stalled",
                                        "created_at": "2026-10-20T11:00:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "checkout_id": "c7e1a9d4-2b63-4f58-9a07-5d8e3c1b6f24",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "provider": "stripe",
                                            "surface": "bot",
                                            "started_at": "2026-10-20T09:52:00+00:00",
                                            "stalled_at": "2026-10-20T11:00:00+00:00",
                                            "enrollment_id": "a4c7e912-3b5d-4f80-9e16-7d2a8c5b4f03"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "checkout"
            }
        },
        "checkout.recovered": {
            "post": {
                "operationId": "webhook.checkout.recovered",
                "description": "### When this fires\n\nThe payment ledger recorded a successful charge for the member, through any door and on any rail, while one of their checkouts stood stalled. Every open checkout of the member closes on that charge; the event fires for each one that had stalled, with the charge and the membership it became, and the passage that was running when they came back. The passage itself ends as `sequence.converted` through the same charge.\n\n### Caveats\n\n- The charge need not be for the stalled plan: a member who stalled on the monthly plan and bought the annual one is recovered all the same.\n- A member who holds a live membership before the window passes never stalls, so never recovers; their checkouts close without an event.\n\n### Related events\n\n- `checkout.stalled`: the stall this recovers.\n- `payment.succeeded`: the charge.\n- `sequence.converted`: the passage ending as a win on the same charge.",
                "summary": "A charge settled for a member whose checkout had stalled.",
                "tags": [
                    "checkout.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "checkout.recovered"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `checkout.recovered` here.",
                                        "enum": [
                                            "checkout.recovered"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "checkout_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The ledger row `checkout.stalled` named."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member's project-scoped user id."
                                            },
                                            "plan_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The plan the stalled checkout was for; the charge may have bought another."
                                            },
                                            "provider": {
                                                "type": "string",
                                                "description": "The rail the stalled checkout opened on, not necessarily the one that settled."
                                            },
                                            "surface": {
                                                "type": "string",
                                                "description": "Where the stalled checkout started.",
                                                "enum": [
                                                    "portal",
                                                    "bot"
                                                ]
                                            },
                                            "payment_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The charge that completed it."
                                            },
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The membership the charge belongs to."
                                            },
                                            "enrollment_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The passage that was running when the member came back, or `null`."
                                            },
                                            "stalled_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the stall was counted."
                                            },
                                            "recovered_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the charge settled."
                                            }
                                        },
                                        "required": [
                                            "checkout_id",
                                            "subscriber_id",
                                            "plan_id",
                                            "provider",
                                            "surface",
                                            "payment_id",
                                            "subscription_id",
                                            "enrollment_id",
                                            "stalled_at",
                                            "recovered_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "checkout.recovered",
                                        "created_at": "2026-10-21T08:30:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "checkout_id": "c7e1a9d4-2b63-4f58-9a07-5d8e3c1b6f24",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "provider": "stripe",
                                            "surface": "bot",
                                            "payment_id": "9f2c7b1e-4d83-4a56-b0e9-7c5d2a8f3b61",
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "enrollment_id": "a4c7e912-3b5d-4f80-9e16-7d2a8c5b4f03",
                                            "stalled_at": "2026-10-20T11:00:00+00:00",
                                            "recovered_at": "2026-10-21T08:30:00+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "checkout"
            }
        },
        "member.lead_created": {
            "post": {
                "operationId": "webhook.member.lead_created",
                "description": "### When this fires\n\nSomebody the project had never seen opened its bot, arrived through a Smart Link or a referral link, signed in to its portal or wrote to its support, and a member row was created for them with the status `lead`. It fires once per row, whichever door they came through, the moment the row is written; it never fires for a connected account adopted from a sibling project or linked by a backfill, because nobody just walked in. The lead sequences of Lead nurture enrol the member on the same event.\n\n### Caveats\n\n- The payload carries no name and no connected account. Resolve the member with [the member endpoint](https://docs.subscriby.net/api/v1/reference/members) using `data.subscriber_id`.\n- A lead who buys later raises `subscription.activated` (a paid checkout) or `subscription.created` (an access code or a cardless trial) with the same `subscriber_id`; a lead who leaves without buying raises nothing more.\n\n### Related events\n\n- `sequence.enrolled`: the lead sequences the arrival enrols the member in, with `trigger` `lead`.\n- `subscription.activated`: the paid-checkout join signal.",
                "summary": "A member row was created as a lead.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.lead_created"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.lead_created` here.",
                                        "enum": [
                                            "member.lead_created"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member's project-scoped user id."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors the envelope `project_id`."
                                            },
                                            "source": {
                                                "type": "string",
                                                "description": "How the account that brought them was linked: a bot's first contact, a portal sign-in, or a handshake the portal opened.",
                                                "enum": [
                                                    "bot",
                                                    "portal",
                                                    "handshake"
                                                ]
                                            },
                                            "smart_link_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The Smart Link credited with the member when one was, else `null`."
                                            },
                                            "created_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the row was written."
                                            }
                                        },
                                        "required": [
                                            "subscriber_id",
                                            "project_id",
                                            "source",
                                            "smart_link_id",
                                            "created_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.lead_created",
                                        "created_at": "2026-10-20T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "source": "bot",
                                            "smart_link_id": "a0c3e8d1-5f27-4b9e-8c64-3d1f2a7b6e95",
                                            "created_at": "2026-10-20T10:05:00+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.joined": {
            "post": {
                "operationId": "webhook.member.joined",
                "description": "### When this fires\n\nA subscriber redeems an access code against a plan with no trial window, gaining access to the project.\n\nThat is the only path that emits this event. A card, wallet, or crypto checkout emits `subscription.activated` and `payment.succeeded`, but no `member.*` join event at all. If the redeemed plan carries a trial, `member.trial_joined` fires instead of this event.\n\n> This event is **access-code-only**. Paid checkouts do not emit it. For a paying audience, use `subscription.activated` as the join signal.\n\n### Caveats\n\n- The payload does not carry the subscriber's connected accounts. Resolve them with [the member endpoint](https://docs.subscriby.net/api/v1/reference/members) using `data.subscriber_id`, which embeds `identities`, one row per connected account with the connector key and the platform's own id.\n- Resource-level grants emit separate `member.resource_added` events as the dispatcher processes each invite.\n- This event always accompanies `subscription.created` and `access_code.redeemed` for the same subscription.\n\n### Related events\n\n- `subscription.activated`: the paid-checkout join signal.\n- `subscription.created`: fires alongside on this path.\n- `member.trial_joined`: trial counterpart.",
                "summary": "A subscriber joins by redeeming an access code against a paid plan.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.joined"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.joined` here.",
                                        "enum": [
                                            "member.joined"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription that triggered the join."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors the envelope `project_id`."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "access_code": {
                                                "type": "string",
                                                "description": "The **full redeemed code**, not masked. Always present."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "project_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "access_code"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.joined",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "access_code": "SLATE-SUNDAY-4F2A9"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.trial_joined": {
            "post": {
                "operationId": "webhook.member.trial_joined",
                "description": "### When this fires\n\nTwo paths emit this event:\n\n- **Cardless trial start**: a subscriber begins a trial that took no payment method.\n- **Access-code redemption on a trial plan**: the redeemed plan sets `trial_ends_at`, so this fires in place of `member.joined`.\n\nA Stripe checkout that begins with a trial window emits `subscription.activated` and `subscription.trial_started`, but no `member.*` join event. Like `member.joined`, this event covers zero-payment acquisition only.\n\nThe `data` keys differ by path. Absent keys are **omitted entirely**, not sent as `null`.\n\n### Caveats\n\n- A trial-joined member emits `member.converted` if the trial converts to paid, or rolls into `member.churned` once the trial expires without converting.\n- `member.converted` is currently emitted for **Stripe only**. Trials taken through other providers will not produce a conversion event.\n- `subscription.created` and `subscription.trial_started` fire alongside this event on both paths.\n\n### Related events\n\n- `subscription.trial_started`: fires alongside.\n- `member.converted`: fires on successful trial conversion (Stripe only).\n- `member.joined`: non-trial counterpart.",
                "summary": "A subscriber joins on a trial via cardless trial or access-code redemption.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.trial_joined"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.trial_joined` here.",
                                        "enum": [
                                            "member.trial_joined"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription that triggered the join."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "trial_ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Cardless-trial path only."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Access-code path only. Mirrors the envelope `project_id`."
                                            },
                                            "access_code": {
                                                "type": "string",
                                                "description": "Access-code path only. The **full redeemed code**, not masked."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload-cardless-trial-start": {
                                    "summary": "cardless trial start",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.trial_joined",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "trial_ends_at": "2026-05-25T10:05:00Z"
                                        }
                                    }
                                },
                                "payload-access-code-redemption-on-a-trial-plan": {
                                    "summary": "access-code redemption on a trial plan",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.trial_joined",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "access_code": "TRIAL-7C1B4"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.converted": {
            "post": {
                "operationId": "webhook.member.converted",
                "description": "### When this fires\n\nA trial subscription successfully converts to a paying subscription: the subscription reaches `active` while the subscriber was previously in `trialing` status. Fires exactly once per conversion.\n\nThis event is currently emitted for **Stripe only**. Trials taken through PayPal, Paystack, Razorpay, Skrill, CeyPay, or CoinPayments do not produce a conversion event; detect those by watching `payment.succeeded` against a subscription you know began in trial.\n\n### Caveats\n\n- Pairs with `payment.succeeded` for the converting charge. `subscription.activated` does **not** fire at conversion; it already fired when the trialing subscription was first created.\n- A subscriber who churns and starts a new trial later does not re-emit `member.converted` for the prior trial; each trial-conversion is its own bounded event.\n\n### Related events\n\n- `member.trial_joined`: predecessor.\n- `subscription.activated`: fired earlier, when the trialing subscription was created; it does not repeat at conversion.",
                "summary": "A trial converts to a paying subscription.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.converted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.converted` here.",
                                        "enum": [
                                            "member.converted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription that converted."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the subscription is on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "provider": {
                                                "type": "string",
                                                "description": "Provider slug for the converting charge."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "provider"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.converted",
                                        "created_at": "2026-05-25T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "provider": "stripe"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.churned": {
            "post": {
                "operationId": "webhook.member.churned",
                "description": "### When this fires\n\nA subscriber's last subscription is expired (by the five-minute expiry sweep, by a refund that ends access, or by a cancelled pass window) and no other subscription of theirs is still active. A cancellation or a failed payment does not churn the member on its own; churn follows only once the subscription is actually expired.\n\n### Caveats\n\n- A subscriber with multiple overlapping subscriptions does not churn until the last one ends.\n- `member.churned` does not delete the subscriber row; if they re-subscribe later, a paid checkout emits `subscription.activated` and an access-code redemption emits `member.joined`.\n\n### Related events\n\n- `subscription.expired`: typical predecessor.\n- `member.joined`: only if they return via an access code.",
                "summary": "A subscriber's last active subscription lapsed.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.churned"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.churned` here.",
                                        "enum": [
                                            "member.churned"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription that lapsed."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the lapsed subscription was on."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "last_plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Duplicate of `plan_id`, kept for backwards compatibility."
                                            },
                                            "ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the subscription ended."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "last_plan_id",
                                            "ends_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.churned",
                                        "created_at": "2026-06-18T10:06:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "last_plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "ends_at": "2026-06-18T10:05:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.removed": {
            "post": {
                "operationId": "webhook.member.removed",
                "description": "### When this fires\n\nA creator manually removes a subscriber from the project. The subscriber is soft-deleted, their access is revoked, and any active subscription is cancelled.\n\n### Caveats\n\n- Distinct from a ban: removed subscribers can rejoin, banned subscribers cannot. See `member.banned`.\n- Distinct from a kick, which moves the subscriber to churned without soft-deleting the row. See `member.kicked`.\n\n### Related events\n\n- `member.banned`, `member.kicked`: alternative discipline events.\n- `subscription.cancelled`: fires alongside if there was an active subscription.",
                "summary": "A subscriber is soft-deleted manually.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.removed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.removed` here.",
                                        "enum": [
                                            "member.removed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscriber": {
                                                "type": "object",
                                                "description": "The member's id and status only.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Subscriber's project-scoped user id."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "The member's status at the moment of removal, captured before the soft-delete. Removal writes no new status.",
                                                        "enum": [
                                                            "lead",
                                                            "trialing",
                                                            "customer",
                                                            "churned",
                                                            "banned"
                                                        ]
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "status"
                                                ]
                                            },
                                            "reason": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Reason supplied by the creator at removal time."
                                            }
                                        },
                                        "required": [
                                            "subscriber",
                                            "reason"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.removed",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscriber": {
                                                "id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "status": "customer"
                                            },
                                            "reason": "creator_manual"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.banned": {
            "post": {
                "operationId": "webhook.member.banned",
                "description": "### When this fires\n\nA creator bans a subscriber. Their access is revoked, the connector removes them from all linked resources, and they cannot re-join the project until the ban is lifted.\n\n### Caveats\n\n- Bans persist across subscription cycles until explicitly lifted via `member.unbanned`.\n- Active subscriptions are cancelled in the same flow; expect `subscription.cancelled`.\n\n### Related events\n\n- `member.unbanned`: paired transition.\n- `member.kicked`: softer discipline.",
                "summary": "A creator bans a subscriber.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.banned"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.banned` here.",
                                        "enum": [
                                            "member.banned"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscriber": {
                                                "type": "object",
                                                "description": "The member's id and status only.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Subscriber's project-scoped user id."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "Always `banned` for this event."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "status"
                                                ]
                                            },
                                            "reason": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Reason supplied at ban time."
                                            }
                                        },
                                        "required": [
                                            "subscriber",
                                            "reason"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.banned",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscriber": {
                                                "id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "status": "banned"
                                            },
                                            "reason": "spam"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.unbanned": {
            "post": {
                "operationId": "webhook.member.unbanned",
                "description": "### When this fires\n\nA creator lifts a previously applied ban. The subscriber returns to a churned state: they can re-subscribe, but they do not automatically regain access to past subscriptions.\n\n### Caveats\n\n- Unbanning does not restore prior subscriptions; the subscriber must purchase a new one to regain access.\n- A subsequent purchase fires `subscription.activated`; only an access-code redemption fires `member.joined`.\n\n### Related events\n\n- `member.banned`: paired transition.\n- `subscription.activated`: fires if the subscriber repurchases.",
                "summary": "A ban is lifted; the subscriber returns to churned status.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.unbanned"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.unbanned` here.",
                                        "enum": [
                                            "member.unbanned"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscriber": {
                                                "type": "object",
                                                "description": "The member's id and status only.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Subscriber's project-scoped user id."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "Always `churned` for this event."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "status"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "subscriber"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.unbanned",
                                        "created_at": "2026-05-22T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscriber": {
                                                "id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "status": "churned"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.kicked": {
            "post": {
                "operationId": "webhook.member.kicked",
                "description": "### When this fires\n\nA creator kicks a subscriber without banning them. The member's status moves to churned, every active subscription is cancelled, and the connector evicts them from every resource they held. The only difference from a ban is that a kick can be reversed by re-subscribing, whereas a ban blocks re-entry until it is lifted.\n\n### Caveats\n\n- A kick evicts the member from every resource their subscriptions granted; expect one `member.resource_removed` per resource.\n- Every active subscription is cancelled in the same flow; expect `subscription.cancelled` for each.\n\n### Related events\n\n- `member.banned`: escalation path.\n- `member.resource_removed`: paired resource event.",
                "summary": "A subscriber is kicked from the project without a ban.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.kicked"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.kicked` here.",
                                        "enum": [
                                            "member.kicked"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscriber": {
                                                "type": "object",
                                                "description": "The member's id and status only.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Subscriber's project-scoped user id."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "Always `churned`: a kick moves the member to churned before the event is emitted."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "status"
                                                ]
                                            },
                                            "reason": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Reason supplied at kick time."
                                            }
                                        },
                                        "required": [
                                            "subscriber",
                                            "reason"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.kicked",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscriber": {
                                                "id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "status": "churned"
                                            },
                                            "reason": "off_topic"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.resource_added": {
            "post": {
                "operationId": "webhook.member.resource_added",
                "description": "### When this fires\n\nSubscriby asks the resource's connector to give a subscriber access to one of the resources their subscription grants (on a connector that grants by link, a join-request invite link named after them) and writes the grant to the access ledger. Each resource grant emits its own event. The event marks the grant, not the subscriber's arrival: they may not have opened the link yet; the ledger row named by `grant_id` moves from `pending` to `granted` when they do. A manual perk arrives here too, once the creator completes its task (`creator_task.completed` precedes it).\n\n### Caveats\n\n- Ordering against the join event is not guaranteed: the dispatcher is queued before `member.joined` is emitted on the access-code path, and paid joins emit no `member.*` join event at all. Treat resource events as independent.\n- A manual perk emits this event only when its creator task is completed, never at purchase; until then the member's grant is `pending` and `creator_task.opened` is what fired.\n\n### Related events\n\n- `member.resource_removed`: paired transition.\n- `member.joined`, `member.trial_joined`: typical predecessors.",
                "summary": "A subscriber gains access to a specific resource.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.resource_added"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.resource_added` here.",
                                        "enum": [
                                            "member.resource_added"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription that authorized the grant."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "resource_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Resource that was granted."
                                            },
                                            "resource_kind": {
                                                "type": "string",
                                                "description": "The resource's kind: `manual`, or `connector:kind` (`telegram:channel`)."
                                            },
                                            "connector": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector that gave the access; `null` for a manual perk the creator handed over."
                                            },
                                            "grant_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The access ledger row; read it back with [the subscription grants endpoint](https://docs.subscriby.net/api/v1/reference/subscriptions)."
                                            },
                                            "mode": {
                                                "type": "string",
                                                "description": "How access was given: a personal invite link the member must use, a membership the connector added, a role, or a task for the creator.",
                                                "enum": [
                                                    "bearer_link",
                                                    "membership",
                                                    "role",
                                                    "creator_task"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "resource_id",
                                            "resource_kind",
                                            "connector",
                                            "grant_id",
                                            "mode"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.resource_added",
                                        "created_at": "2026-05-18T10:05:30Z",
                                        "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",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "resource_kind": "telegram:channel",
                                            "connector": "telegram",
                                            "grant_id": "7d1c3e9a-2b64-4f0e-9a58-3c6b1d8e2f47",
                                            "mode": "bearer_link"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.resource_pending": {
            "post": {
                "operationId": "webhook.member.resource_pending",
                "description": "### When this fires\n\nA purchase entitles a subscriber to a resource on a connector where the subscriber has no connected account: a member who bought on the portal with only an email, or a plan that spans a connector the member has not linked. Nothing can be issued, so the access ledger records a grant in state `pending_identity` and this event says so. The moment the member connects an account on that connector (from the portal, by signing in through the connector, or by adopting an account from a sibling project), the grant is issued and `member.resource_added` follows with the same `grant_id`.\n\n### Caveats\n\n- One event per resource the purchase entitles the member to on that connector; a plan with three channels raises three, all waiting on the same account.\n- Nothing is sent to the member by the bot; it cannot reach them yet. The portal shows the pending access on the membership card; an integration that wants to nudge them should use the email it holds.\n- A subscription that ends before the account is connected leaves the grant `pending_identity` in the ledger; no `member.resource_removed` is raised for access that was never given.\n\n### Related events\n\n- `member.resource_added`: raised for the same `grant_id` once the account is connected and access is issued.\n- `member.identity_linked`: the act that releases the pending grants.",
                "summary": "A subscriber is entitled to a resource but has no account on its connector yet, so access waits for them to connect one.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.resource_pending"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.resource_pending` here.",
                                        "enum": [
                                            "member.resource_pending"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription that entitles the member."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "resource_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Resource the member is waiting to be admitted to."
                                            },
                                            "resource_kind": {
                                                "type": "string",
                                                "description": "The resource's kind: `manual`, or `connector:kind` (`telegram:channel`)."
                                            },
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector the member needs an account on."
                                            },
                                            "grant_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The access ledger row, in state `pending_identity`; read it with [the subscription grants endpoint](https://docs.subscriby.net/api/v1/reference/subscriptions)."
                                            },
                                            "mode": {
                                                "type": "string",
                                                "description": "How access will be given once the account is connected.",
                                                "enum": [
                                                    "bearer_link",
                                                    "membership",
                                                    "role",
                                                    "creator_task"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "resource_id",
                                            "resource_kind",
                                            "connector",
                                            "grant_id",
                                            "mode"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.resource_pending",
                                        "created_at": "2026-09-12T10:05:30Z",
                                        "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",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "resource_kind": "telegram:channel",
                                            "connector": "telegram",
                                            "grant_id": "7d1c3e9a-2b64-4f0e-9a58-3c6b1d8e2f47",
                                            "mode": "bearer_link"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.resource_reissued": {
            "post": {
                "operationId": "webhook.member.resource_reissued",
                "description": "### When this fires\n\nA creator (over the API, an MCP agent, or the members page) asks for a subscriber's access to be reissued: the grant the subscriber held on a resource is revoked (on a connector that grants by link, the personal invite link dies) and the dispatcher that grants at purchase runs again to issue a fresh one. Each resource emits its own event, and `member.resource_added` follows for the new grant. The member's own **Refresh invite links** in the bot does the same and raises the same event.\n\n### Caveats\n\n- Revoking the old grant is best effort: a link the platform no longer knows is treated as already gone, and the reissue goes ahead regardless.\n- The member is messaged the fresh links by the bot when it can reach them, so do not follow this event with a nudge of your own.\n\n### Related events\n\n- `member.resource_added`: the fresh grant, moments later.\n- `member.resource_removed`: access taken away without a replacement.",
                "summary": "A subscriber's access to a resource is being reissued: the old grant is revoked and a fresh one follows.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.resource_reissued"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.resource_reissued` here.",
                                        "enum": [
                                            "member.resource_reissued"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription whose access is being reissued."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "resource_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Resource the grant was revoked on."
                                            },
                                            "resource_kind": {
                                                "type": "string",
                                                "description": "The resource's kind: `manual`, or `connector:kind` (`telegram:channel`)."
                                            },
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector the grant was on."
                                            },
                                            "grant_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The **revoked** ledger row; the fresh grant arrives on `member.resource_added` with its own id. Null when the ledger held no row for the old link."
                                            },
                                            "mode": {
                                                "type": "string",
                                                "description": "How access was given.",
                                                "enum": [
                                                    "bearer_link",
                                                    "membership",
                                                    "role",
                                                    "creator_task"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "resource_id",
                                            "resource_kind",
                                            "connector",
                                            "grant_id",
                                            "mode"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.resource_reissued",
                                        "created_at": "2026-09-12T10:05:30Z",
                                        "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",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "resource_kind": "telegram:channel",
                                            "connector": "telegram",
                                            "grant_id": "7d1c3e9a-2b64-4f0e-9a58-3c6b1d8e2f47",
                                            "mode": "bearer_link"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.access_extended": {
            "post": {
                "operationId": "webhook.member.access_extended",
                "description": "### When this fires\n\nA [connector outage](https://docs.subscriby.net/disaster-recovery/connector-outages) that lasted an hour or more ended because the connector recovered or was replaced, and the project's **Outage Compensation** setting is on. Every purchase that grants access right now and unlocks a place on that connector has the outage's length banked, and this event fires once for each of them.\n\n`applies_at` says when the member feels it:\n\n- `now`: a one-time or lifetime-style purchase with a fixed end. `ends_at` has already moved later by `extended_seconds`.\n- `membership_end`: a recurring plan. No gateway lets a renewal move by a few hours, so the time is banked instead: the member's access always runs `banked_seconds` past the period they last paid for, and they receive the time when the membership ends, whether they cancel, lapse or a renewal fails. Their renewal date and charges do not change.\n\n`banked_seconds` is the purchase's running total across every outage it lived through; `extended_seconds` is what this outage added. The member is told in the chat their connector binds to them and by email; the same fact shows on their portal card and in the bot.\n\n### Caveats\n\n- Passes and series are never extended: a dated window cannot move, so no event fires for them.\n- Perk-only plans are not affected by an outage and receive nothing.\n- A project that switched **Outage Compensation** off, an outage shorter than an hour, or one that ended with an uninstall, fires no `member.access_extended` at all; `connector.outage_compensated` still fires with `members_extended: 0`.\n\n### Related events\n\n- `connector.outage_compensated`: the one-line settlement summary that follows these.\n- `connector.outage_closed`: the outage this compensates.",
                "summary": "Outage Compensation banked the length of a connector outage on a member's purchase: one event per member, saying when they feel the extra time.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.access_extended"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.access_extended` here.",
                                        "enum": [
                                            "member.access_extended"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "applies_at": {
                                                "type": "string",
                                                "description": "`now` for a fixed-term purchase whose end moved, `membership_end` for a recurring plan.",
                                                "enum": [
                                                    "now",
                                                    "membership_end"
                                                ]
                                            },
                                            "banked_seconds": {
                                                "type": "integer",
                                                "description": "The purchase's running total of banked outage time, after this outage. Also `compensation_seconds` on the subscription object."
                                            },
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector that was refused."
                                            },
                                            "ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "The purchase's end after the addition; for a recurring plan it already includes the banked time."
                                            },
                                            "extended_seconds": {
                                                "type": "integer",
                                                "description": "What this outage added, its length in seconds."
                                            },
                                            "outage_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The outage row, the same id `connector.outage_opened` and `connector.outage_closed` carried."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors top-level `project_id`."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member."
                                            },
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The purchase."
                                            }
                                        },
                                        "required": [
                                            "applies_at",
                                            "banked_seconds",
                                            "connector",
                                            "ends_at",
                                            "extended_seconds",
                                            "outage_id",
                                            "project_id",
                                            "subscriber_id",
                                            "subscription_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.access_extended",
                                        "created_at": "2026-09-13T13:21:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "applies_at": "membership_end",
                                            "banked_seconds": 11700,
                                            "connector": "telegram",
                                            "ends_at": "2026-10-13T13:20:00Z",
                                            "extended_seconds": 11700,
                                            "outage_id": "9c1e4d2a-7b3f-4e8a-a2d1-5f6b7c8d9e0f",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.resource_removed": {
            "post": {
                "operationId": "webhook.member.resource_removed",
                "description": "### When this fires\n\nA subscriber is evicted from a specific resource: after a subscription expires or is cancelled, after a ban, kick or removal, or when a pass window closes or is cancelled. Each resource revocation emits its own event. Nothing is emitted when another still-active subscription of theirs grants the same resource: the invite link is revoked but the member stays in.\n\n### Caveats\n\n- Multiple revocations for the same subscriber typically arrive in close succession when a subscription expires; use `SB-Event-Id` for dedupe.\n- A manual perk emits this event only when its grant is revoked on the ledger; a place a connector gates emits it once the connector has been asked to remove the member.\n\n### Related events\n\n- `member.resource_added`: paired transition.\n- `subscription.expired`, `subscription.cancelled`, `member.kicked`: typical triggers.",
                "summary": "A subscriber loses access to a specific resource.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.resource_removed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.resource_removed` here.",
                                        "enum": [
                                            "member.resource_removed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription whose grant was revoked."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "resource_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Resource the subscriber lost access to."
                                            },
                                            "resource_kind": {
                                                "type": "string",
                                                "description": "The resource's kind: `manual`, or `connector:kind` (`telegram:channel`)."
                                            },
                                            "connector": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector the member was removed through."
                                            },
                                            "grant_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The access ledger row that ended, now `revoked`; read it back with [the subscription grants endpoint](https://docs.subscriby.net/api/v1/reference/subscriptions). Null when the ledger never held a grant for this resource."
                                            },
                                            "mode": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "How the access had been given.",
                                                "enum": [
                                                    "bearer_link",
                                                    "membership",
                                                    "role",
                                                    "creator_task",
                                                    null
                                                ]
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "subscriber_id",
                                            "resource_id",
                                            "resource_kind",
                                            "connector",
                                            "grant_id",
                                            "mode"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.resource_removed",
                                        "created_at": "2026-06-18T10:06:00Z",
                                        "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",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "resource_kind": "telegram:channel",
                                            "connector": "telegram",
                                            "grant_id": "7d1c3e9a-2b64-4f0e-9a58-3c6b1d8e2f47",
                                            "mode": "bearer_link"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.identity_linked": {
            "post": {
                "operationId": "webhook.member.identity_linked",
                "description": "### When this fires\n\nA member of the project gains a connected account on a connector: the platform account that signs them in to the portal and that the project's bot knows them by. Three doors raise it: the member completes **Connect …** from the portal's Account & Recovery screen and the project's bot confirms the account; the member signs in to the portal through a connector the project had not seen them on before; or the member taps **Use the same account** to adopt an account they already use in another of the creator's projects. Each connected account emits its own event. Nothing is emitted when an account the member already holds is confirmed again.\n\n### Caveats\n\n- `identity_id` is the account row, not the link: the same value appears in `member.identity_unlinked` and in the `identities` of [the member endpoint](https://docs.subscriby.net/api/v1/reference/members). The link's own `id` (what the disconnect endpoint takes) is only in the REST payloads.\n- Accounts the bot creates on first contact are mirrored into the identity tables without raising this event; it is reserved for acts the member takes.\n\n### Related events\n\n- `member.identity_unlinked`: paired transition.",
                "summary": "A subscriber connects a platform account to their membership.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.identity_linked"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.identity_linked` here.",
                                        "enum": [
                                            "member.identity_linked"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "identity_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The connector account row. One account is one row however many projects link it."
                                            },
                                            "connector": {
                                                "type": "string",
                                                "description": "Connector key the account is on."
                                            },
                                            "external_id": {
                                                "type": "string",
                                                "description": "The platform's own id for the account."
                                            },
                                            "display_name": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "What the platform calls the person, when known."
                                            },
                                            "source": {
                                                "type": "string",
                                                "description": "How the link was proven. `handshake` covers both Connect … and a portal sign-in.",
                                                "enum": [
                                                    "handshake",
                                                    "portal",
                                                    "adopted",
                                                    "bot",
                                                    "backfill"
                                                ]
                                            },
                                            "preferred": {
                                                "type": "boolean",
                                                "description": "Whether this account is the one the project reaches first. A member's first account is."
                                            }
                                        },
                                        "required": [
                                            "subscriber_id",
                                            "identity_id",
                                            "connector",
                                            "external_id",
                                            "display_name",
                                            "source",
                                            "preferred"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.identity_linked",
                                        "created_at": "2026-09-12T10:06:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "identity_id": "0c2d8a7e-4b1f-4d3e-9a6b-2f5e8c1d7a90",
                                            "connector": "telegram",
                                            "external_id": "123456789",
                                            "display_name": "Ada Lovelace",
                                            "source": "handshake",
                                            "preferred": true
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "member.identity_unlinked": {
            "post": {
                "operationId": "webhook.member.identity_unlinked",
                "description": "### When this fires\n\nA connected account is removed from a member: by the member on the portal's Account & Recovery screen (**Disconnect**), or by the creator over [the disconnect endpoint](https://docs.subscriby.net/api/v1/reference/members) or the `unlink_member_identity` MCP tool. The account stops signing the member in to the portal and the project's bot stops knowing them by it. Nothing is emitted when the removal is refused because the account was the member's last way to sign in.\n\n### Caveats\n\n- The member keeps their subscriptions and grants; only the way they sign in and are reached changes. A member with no connected account left is reached by email.\n- The event does not say who asked. Read the activity log for the actor when it matters.\n\n### Related events\n\n- `member.identity_linked`: paired transition.",
                "summary": "A subscriber's connected platform account is disconnected from their membership.",
                "tags": [
                    "member.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "member.identity_unlinked"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `member.identity_unlinked` here.",
                                        "enum": [
                                            "member.identity_unlinked"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "identity_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The connector account row that was disconnected. Matches `member.identity_linked`."
                                            },
                                            "connector": {
                                                "type": "string",
                                                "description": "Connector key the account was on."
                                            },
                                            "external_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The platform's own id for the account."
                                            }
                                        },
                                        "required": [
                                            "subscriber_id",
                                            "identity_id",
                                            "connector",
                                            "external_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "member.identity_unlinked",
                                        "created_at": "2026-09-12T10:06:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "identity_id": "0c2d8a7e-4b1f-4d3e-9a6b-2f5e8c1d7a90",
                                            "connector": "telegram",
                                            "external_id": "123456789"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-user:view"
                ],
                "x-webhook-family": "member"
            }
        },
        "creator_task.opened": {
            "post": {
                "operationId": "webhook.creator_task.opened",
                "description": "### When this fires\n\nA subscription becomes active (or a pass window opens) on a plan that includes a **manual** resource: a perk no connector can give, which the creator hands over themselves. The access ledger records a `creator_task` grant in state `pending` and opens a task naming the member and the perk; this event carries that task. One event per manual resource the purchase entitles the member to. Nothing is sent to the member by a bot for a manual perk; the portal shows the perk as arranged by the organiser.\n\n### Caveats\n\n- A task is opened once per purchase, resource and window; a retry of the granting job does not open a second one.\n- A purchase that ends before the task is done revokes the grant; the task then drops out of the open list without a `creator_task.completed`.\n\n### Related events\n\n- `creator_task.completed`: the task is done and the grant issued.\n- `member.resource_added`: raised for the same `grant_id` on completion.",
                "summary": "A purchase entitles a subscriber to a manual perk, so the creator has something to do by hand.",
                "tags": [
                    "creator_task.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "creator_task.opened"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `creator_task.opened` here.",
                                        "enum": [
                                            "creator_task.opened"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "task_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The task; what [the complete endpoint](https://docs.subscriby.net/api/v1/reference/creator-tasks) takes."
                                            },
                                            "grant_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The access ledger row, in state `pending` with mode `creator_task`."
                                            },
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription that entitles the member."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "resource_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The manual resource."
                                            },
                                            "resource_kind": {
                                                "type": "string",
                                                "description": "Always `manual`: only a manual perk opens a creator task."
                                            },
                                            "instructions": {
                                                "type": "string",
                                                "description": "What the creator has to do, in the creator's locale: the member's name and the perk."
                                            },
                                            "due_at": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "date-time",
                                                "description": "When the perk is due; null for continuous access, the window's start for a dated pass."
                                            }
                                        },
                                        "required": [
                                            "task_id",
                                            "grant_id",
                                            "subscription_id",
                                            "subscriber_id",
                                            "resource_id",
                                            "resource_kind",
                                            "instructions",
                                            "due_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "creator_task.opened",
                                        "created_at": "2026-09-12T10:05:30Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "task_id": "9e4b2c71-3d58-4a6f-b0e2-7c1d5f8a9b34",
                                            "grant_id": "7d1c3e9a-2b64-4f0e-9a58-3c6b1d8e2f47",
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "resource_kind": "manual",
                                            "instructions": "Give Ada Lovelace access to Welcome packet.",
                                            "due_at": null
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "creator_task"
            }
        },
        "creator_task.completed": {
            "post": {
                "operationId": "webhook.creator_task.completed",
                "description": "### When this fires\n\nThe creator (or a teammate, an integration or an agent on their behalf) marks a creator task done: on the members page, through [the complete endpoint](https://docs.subscriby.net/api/v1/reference/creator-tasks) or the MCP tool [`complete_creator_task`](https://docs.subscriby.net/mcp/v1/tools/creator-task/complete-creator-task). The access ledger row moves from `pending` to `granted`, this event says who did it, and `member.resource_added` follows for the same `grant_id` with mode `creator_task`.\n\n### Caveats\n\n- Completing a task is not idempotent over the API: a second call for a completed task answers `422 VALIDATION_FAILED`.\n- The member is not messaged by a bot on completion; tell them yourself, or let the portal show the perk as delivered.\n\n### Related events\n\n- `creator_task.opened`: the task being done.\n- `member.resource_added`: raised for the same grant on completion.",
                "summary": "The creator marked a manual perk as handed over; the grant is issued.",
                "tags": [
                    "creator_task.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "creator_task.completed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `creator_task.completed` here.",
                                        "enum": [
                                            "creator_task.completed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "task_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The task that was completed."
                                            },
                                            "grant_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The access ledger row, now `granted`."
                                            },
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription that entitles the member."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "resource_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The manual resource."
                                            },
                                            "resource_kind": {
                                                "type": "string",
                                                "description": "Always `manual`: only a manual perk opens a creator task."
                                            },
                                            "completed_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When it was marked done."
                                            },
                                            "completed_by_user_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The creator or teammate who marked it done."
                                            }
                                        },
                                        "required": [
                                            "task_id",
                                            "grant_id",
                                            "subscription_id",
                                            "subscriber_id",
                                            "resource_id",
                                            "resource_kind",
                                            "completed_at",
                                            "completed_by_user_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "creator_task.completed",
                                        "created_at": "2026-09-12T10:35:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "task_id": "9e4b2c71-3d58-4a6f-b0e2-7c1d5f8a9b34",
                                            "grant_id": "7d1c3e9a-2b64-4f0e-9a58-3c6b1d8e2f47",
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "resource_kind": "manual",
                                            "completed_at": "2026-09-12T10:35:00Z",
                                            "completed_by_user_id": "0a7d3c1e-5b28-4f96-a3e1-6d9c2b8f4e10"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-subscription:view"
                ],
                "x-webhook-family": "creator_task"
            }
        },
        "connector.installed": {
            "post": {
                "operationId": "webhook.connector.installed",
                "description": "### When this fires\n\nA creator (or a token) installs a connector on a project: from the Connectors tab, through [the install endpoint](https://docs.subscriby.net/api/v1/reference/connectors) or the [`install_connector`](https://docs.subscriby.net/mcp/v1/tools/connectors/install-connector) tool. Installing says \"this project runs this connector\" and opens the row the Connectors tab shows as **pending**; connecting, which hands the connector the creator's credentials, is a separate act and fires `connector.connected`. Installing a connector that is already installed changes nothing and fires nothing; bringing an uninstalled connector back fires this again, the row pending once more with its settings kept.\n\n### Caveats\n\n- A second distinct connector on a project needs the owner's `multi_connector` capability (Growth); the install is refused `CONNECTOR_TIER_REQUIRED` and nothing fires.\n- The first connector's bot flow connects in one step from the dashboard, so an existing project sees `connector.connected` without a preceding `connector.installed`.\n\n### Related events\n\n- `connector.connected`: the credentials handed over.\n- `connector.disconnected`: the reverse.",
                "summary": "A connector was installed on a project: a pending installation with no credentials yet.",
                "tags": [
                    "connector.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "connector.installed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `connector.installed` here.",
                                        "enum": [
                                            "connector.installed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector key, as the [directory](https://docs.subscriby.net/api/v1/reference/connectors) lists it."
                                            },
                                            "installation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The installation row; what the project's connector endpoints return as `id`."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors top-level `project_id`."
                                            },
                                            "state": {
                                                "type": "string",
                                                "description": "Always `pending` here: nothing is connected yet."
                                            }
                                        },
                                        "required": [
                                            "connector",
                                            "installation_id",
                                            "project_id",
                                            "state"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "connector.installed",
                                        "created_at": "2026-09-12T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "connector": "discord",
                                            "installation_id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "state": "pending"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-connector:view"
                ],
                "x-webhook-family": "connector"
            }
        },
        "connector.connected": {
            "post": {
                "operationId": "webhook.connector.connected",
                "description": "### When this fires\n\nA creator completes a connector's connect flow on the dashboard: the connector checks the credentials, registers with its platform and the installation turns `connected`. For the first connector this is the **Connect Bot** modal, the platform bot's connectivity conversation and a Disaster Recovery bot replacement.\n\n### Caveats\n\n- Credentials are never in the payload. Read the installation back with [the installation endpoint](https://docs.subscriby.net/api/v1/reference/connectors).\n- Reconnecting with new credentials fires this again for the same `installation_id`.\n\n### Related events\n\n- `connector.installed`: the pending row that preceded it, when the connector installs in two steps.\n- `connector.status_changed`: the installation's health afterwards.",
                "summary": "The creator connected an installation with their credentials; the connector can act for the project now.",
                "tags": [
                    "connector.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "connector.connected"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `connector.connected` here.",
                                        "enum": [
                                            "connector.connected"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector key."
                                            },
                                            "installation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The installation row."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors top-level `project_id`."
                                            },
                                            "display_name": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The platform's display name for the installation (the bot's name)."
                                            },
                                            "handle": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The platform's handle for the installation (the bot's username), without a leading `@`."
                                            }
                                        },
                                        "required": [
                                            "connector",
                                            "installation_id",
                                            "project_id",
                                            "display_name",
                                            "handle"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "connector.connected",
                                        "created_at": "2026-09-12T10:06:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "connector": "telegram",
                                            "installation_id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "display_name": "Research Bot",
                                            "handle": "research_bot"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-connector:view"
                ],
                "x-webhook-family": "connector"
            }
        },
        "connector.disconnected": {
            "post": {
                "operationId": "webhook.connector.disconnected",
                "description": "### When this fires\n\nA creator disconnects an installation, from the Connectors tab, through [the disconnect endpoint](https://docs.subscriby.net/api/v1/reference/connectors) or the [`disconnect_connector`](https://docs.subscriby.net/mcp/v1/tools/connectors/disconnect-connector) tool. The connector withdraws the installation on its platform, the credentials are wiped and the installation turns `disconnected`; grants, resources, plans and identities are untouched and members keep the access they hold. Disconnecting an installation already disconnected fires nothing.\n\n### Caveats\n\n- Disconnecting is not uninstalling: nothing is revoked and no plan is touched. Uninstalling, with its impact preview, is a separate act and fires `connector.uninstalled`.\n\n### Related events\n\n- `connector.connected`: the reverse.\n- `connector.status_changed`: a platform-side revocation, as opposed to the creator's own disconnect.",
                "summary": "An installation was disconnected: the connector withdrew it, the credentials were wiped, the row stays.",
                "tags": [
                    "connector.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "connector.disconnected"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `connector.disconnected` here.",
                                        "enum": [
                                            "connector.disconnected"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector key."
                                            },
                                            "installation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The installation row, which stays and can be connected again."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors top-level `project_id`."
                                            }
                                        },
                                        "required": [
                                            "connector",
                                            "installation_id",
                                            "project_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "connector.disconnected",
                                        "created_at": "2026-09-12T11:00:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "connector": "telegram",
                                            "installation_id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-connector:view"
                ],
                "x-webhook-family": "connector"
            }
        },
        "connector.status_changed": {
            "post": {
                "operationId": "webhook.connector.status_changed",
                "description": "### When this fires\n\nThe hourly health probe, or a **Verify** run by the creator ([the verify endpoint](https://docs.subscriby.net/api/v1/reference/connectors), [`verify_connector_installation`](https://docs.subscriby.net/mcp/v1/tools/connectors/verify-connector-installation)), recorded a state other than the one the installation had. A probe that finds nothing changed fires nothing.\n\n### Caveats\n\n- `reason` is a stable code in the connector's vocabulary; the sentence for it is `state_detail` on the installation, read from the API.\n- A Disaster Recovery incident opens beside a `degraded` state that warrants a replacement; see `recovery.incident_opened`.\n\n### Related events\n\n- `connector.connected`: a fresh connection that clears a degraded state.\n- `connector.disconnected`: the creator withdrew it on purpose.",
                "summary": "A probe or a verify moved an installation's state: connected, degraded or revoked.",
                "tags": [
                    "connector.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "connector.status_changed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `connector.status_changed` here.",
                                        "enum": [
                                            "connector.status_changed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector key."
                                            },
                                            "installation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The installation row."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors top-level `project_id`."
                                            },
                                            "previous_state": {
                                                "type": "string",
                                                "description": "The state before.",
                                                "enum": [
                                                    "pending",
                                                    "connected",
                                                    "degraded",
                                                    "revoked",
                                                    "disconnected"
                                                ]
                                            },
                                            "state": {
                                                "type": "string",
                                                "description": "The state now.",
                                                "enum": [
                                                    "pending",
                                                    "connected",
                                                    "degraded",
                                                    "revoked",
                                                    "disconnected"
                                                ]
                                            },
                                            "reason": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector's reason code when the state is not `connected`; the same code `state_reason` carries."
                                            }
                                        },
                                        "required": [
                                            "connector",
                                            "installation_id",
                                            "project_id",
                                            "previous_state",
                                            "state",
                                            "reason"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "connector.status_changed",
                                        "created_at": "2026-09-12T06:00:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "connector": "telegram",
                                            "installation_id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "previous_state": "connected",
                                            "state": "degraded",
                                            "reason": "connector_api_unauthorized"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-connector:view"
                ],
                "x-webhook-family": "connector"
            }
        },
        "connector.settings_updated": {
            "post": {
                "operationId": "webhook.connector.settings_updated",
                "description": "### When this fires\n\nA creator changes an installation's settings, on the dashboard, through [the settings endpoint](https://docs.subscriby.net/api/v1/reference/connectors) or the [`update_connector_installation_settings`](https://docs.subscriby.net/mcp/v1/tools/connectors/update-connector-installation-settings) tool, and at least one declared field took a new value. A write that changes nothing fires nothing.\n\n### Caveats\n\n- Values are never in the payload, and the installation endpoints never serialise settings either, because a settings field may be a secret. A consumer that needs the value asks the creator.\n\n### Related events\n\n- `connector.connected`: the installation the settings belong to.",
                "summary": "A declared setting of an installation changed: which fields, never their values.",
                "tags": [
                    "connector.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "connector.settings_updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `connector.settings_updated` here.",
                                        "enum": [
                                            "connector.settings_updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector key."
                                            },
                                            "installation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The installation row."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors top-level `project_id`."
                                            },
                                            "changed_fields": {
                                                "type": "array",
                                                "description": "The declared field names that took a new value, as the connector's `settings_fields` name them, and `capabilities.<key>` for each capability switch that changed.",
                                                "items": {
                                                    "type": "string"
                                                }
                                            }
                                        },
                                        "required": [
                                            "connector",
                                            "installation_id",
                                            "project_id",
                                            "changed_fields"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "connector.settings_updated",
                                        "created_at": "2026-09-12T10:20:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "connector": "discord",
                                            "installation_id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "changed_fields": [
                                                "greeting"
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-connector:view"
                ],
                "x-webhook-family": "connector"
            }
        },
        "connector.uninstalled": {
            "post": {
                "operationId": "webhook.connector.uninstalled",
                "description": "### When this fires\n\nA creator uninstalls a connector from a project, from the Connectors tab, through [the uninstall endpoint](https://docs.subscriby.net/api/v1/reference/connectors) or the [`uninstall_connector`](https://docs.subscriby.net/mcp/v1/tools/connectors/uninstall-connector) tool, after the impact preview. Uninstalling is distinct from disconnecting and never a deletion: every live grant on the connector's resources is revoked (`member.resource_removed` fires per grant), the resources are deactivated as detached with their external ids kept, the installation row stays with `uninstalled_at`, identities are never removed and no money moves by itself. The two opt-ins act on the plans left with nothing to grant: taking them off sale fires `plan.deactivated` per plan, cancelling their recurring subscriptions at period end fires `subscription.cancelled` per subscription.\n\n### Caveats\n\n- Members are told by email that their recurring subscription will not renew; nothing is taken from them before the end of the paid period.\n- Installing the connector again brings the same installation back as pending with its settings kept; the detached resources stay inactive until the creator relinks them.\n\n### Related events\n\n- `connector.disconnected`: the reversible act this is not.\n- `connector.installed`: the reinstall.",
                "summary": "A connector was uninstalled from a project: its grants revoked, its resources detached, the installation row kept, with the counts of what that touched.",
                "tags": [
                    "connector.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "connector.uninstalled"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `connector.uninstalled` here.",
                                        "enum": [
                                            "connector.uninstalled"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector key."
                                            },
                                            "installation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The installation row, kept with `uninstalled_at`."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors top-level `project_id`."
                                            },
                                            "grants_revoked": {
                                                "type": "integer",
                                                "description": "Live grants revoked with reason `connector_uninstalled`; one `member.resource_removed` each."
                                            },
                                            "resources_detached": {
                                                "type": "integer",
                                                "description": "Resources deactivated and marked `detached`."
                                            },
                                            "plans_unpublished": {
                                                "type": "integer",
                                                "description": "Emptied plans taken off sale; `0` when the opt-in was off or nothing was emptied."
                                            },
                                            "subscriptions_cancelled": {
                                                "type": "integer",
                                                "description": "Recurring subscriptions cancelled at period end; `0` when the opt-in was off. One-time purchases are never counted."
                                            }
                                        },
                                        "required": [
                                            "connector",
                                            "installation_id",
                                            "project_id",
                                            "grants_revoked",
                                            "resources_detached",
                                            "plans_unpublished",
                                            "subscriptions_cancelled"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "connector.uninstalled",
                                        "created_at": "2026-09-12T11:30:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "connector": "discord",
                                            "installation_id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "grants_revoked": 41,
                                            "resources_detached": 2,
                                            "plans_unpublished": 1,
                                            "subscriptions_cancelled": 17
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-connector:view"
                ],
                "x-webhook-family": "connector"
            }
        },
        "connector.doctor_completed": {
            "post": {
                "operationId": "webhook.connector.doctor_completed",
                "description": "### When this fires\n\nThe creator pressed **Run Doctor** on the Connectors tab or the connector's page, an integration called [the doctor endpoint](https://docs.subscriby.net/api/v1/reference/connectors) or [`run_connector_doctor`](https://docs.subscriby.net/mcp/v1/tools/connectors/run-connector-doctor), or the platform's scheduled sweep ran, and the report differs from the one kept on the installation: a finding appeared, disappeared or changed severity or state. A run that finds exactly what the last one found fires nothing, so a nightly sweep is quiet until something moves. The installation's own verification inside the run still fires `connector.status_changed` when the state moved.\n\n### Caveats\n\n- The first run on an installation fires this event, because there is no earlier report to match; a repeat with the same findings does not.\n- A resource the connector has no place it can ask about (no space row, no legacy chat) is a `warning` finding, never left out.\n- Sentences are rendered in the creator's language at the time of the run; the `state` words are stable.\n\n### Related events\n\n- `connector.status_changed`: the installation's own verdict, fired by the verification inside the run when the state moved.",
                "summary": "The connector doctor ran on an installation and found something different from the previous run.",
                "tags": [
                    "connector.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "connector.doctor_completed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `connector.doctor_completed` here.",
                                        "enum": [
                                            "connector.doctor_completed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector key."
                                            },
                                            "installation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The installation examined."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The project, repeated inside the payload."
                                            },
                                            "ran_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the doctor ran."
                                            },
                                            "healthy": {
                                                "type": "boolean",
                                                "description": "Whether every finding is `ok`."
                                            },
                                            "critical": {
                                                "type": "integer",
                                                "description": "Findings the connector can no longer act on."
                                            },
                                            "warnings": {
                                                "type": "integer",
                                                "description": "Findings the connector could not confirm."
                                            },
                                            "findings": {
                                                "type": "array",
                                                "description": "Every check, the installation first, then one per gated resource.",
                                                "items": {
                                                    "type": "object",
                                                    "properties": {
                                                        "key": {
                                                            "type": "string",
                                                            "description": "`installation`, or `resource:<resource id>`."
                                                        },
                                                        "kind": {
                                                            "type": "string",
                                                            "description": "What was checked.",
                                                            "enum": [
                                                                "installation",
                                                                "resource"
                                                            ]
                                                        },
                                                        "severity": {
                                                            "type": "string",
                                                            "description": "How the finding stands.",
                                                            "enum": [
                                                                "ok",
                                                                "warning",
                                                                "critical"
                                                            ]
                                                        },
                                                        "subject": {
                                                            "type": "string",
                                                            "description": "What was checked, as the creator names it."
                                                        },
                                                        "state": {
                                                            "type": "string",
                                                            "description": "The connector's word for how it stands: an installation state, or a space access state."
                                                        },
                                                        "message": {
                                                            "type": "string",
                                                            "description": "One sentence in the creator's language."
                                                        },
                                                        "creator_actionable": {
                                                            "type": "boolean",
                                                            "description": "Whether the creator can fix it themselves."
                                                        },
                                                        "fix_url": {
                                                            "type": [
                                                                "string",
                                                                "null"
                                                            ],
                                                            "format": "uri",
                                                            "description": "Where they go to fix it, when there is a page."
                                                        },
                                                        "resource_id": {
                                                            "type": [
                                                                "string",
                                                                "null"
                                                            ],
                                                            "format": "uuid",
                                                            "description": "The resource, for a resource finding."
                                                        }
                                                    },
                                                    "required": [
                                                        "key",
                                                        "kind",
                                                        "severity",
                                                        "subject",
                                                        "state",
                                                        "message",
                                                        "creator_actionable",
                                                        "fix_url",
                                                        "resource_id"
                                                    ]
                                                }
                                            }
                                        },
                                        "required": [
                                            "connector",
                                            "installation_id",
                                            "project_id",
                                            "ran_at",
                                            "healthy",
                                            "critical",
                                            "warnings",
                                            "findings"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "connector.doctor_completed",
                                        "created_at": "2026-09-12T10:07:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "connector": "telegram",
                                            "installation_id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "ran_at": "2026-09-12T10:07:00+00:00",
                                            "healthy": false,
                                            "critical": 1,
                                            "warnings": 0,
                                            "findings": [
                                                {
                                                    "key": "installation",
                                                    "kind": "installation",
                                                    "severity": "ok",
                                                    "subject": "Research Bot",
                                                    "state": "connected",
                                                    "message": "The connector still answers for this installation.",
                                                    "creator_actionable": false,
                                                    "fix_url": null,
                                                    "resource_id": null
                                                },
                                                {
                                                    "key": "resource:b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                                    "kind": "resource",
                                                    "severity": "critical",
                                                    "subject": "Premium Channel",
                                                    "state": "not_member",
                                                    "message": "The bot was removed from this channel.",
                                                    "creator_actionable": true,
                                                    "fix_url": "https://app.subscriby.net/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/resources",
                                                    "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-connector:view"
                ],
                "x-webhook-family": "connector"
            }
        },
        "connector.outage_opened": {
            "post": {
                "operationId": "webhook.connector.outage_opened",
                "description": "### When this fires\n\nThe hourly health probe recorded a platform-caused refusal of a project's **live** installation: the platform says the credentials are revoked or regenerated, or that the bot or app no longer exists. Rate limits, unclassified errors, standby installations and a creator's own **Disconnect** never open an outage. A probe that repeats the same verdict does not fire this again; one outage stays open until `connector.outage_closed`.\n\nWhile the outage is open, every plan that unlocks a place on that connector is off sale on the portal, in the bot, through access codes and trials and through the REST checkout, and the installation object reads `sales_paused: true` with an `outage` block. See [Connector outages](https://docs.subscriby.net/disaster-recovery/connector-outages) for what members and creators see.\n\n### Caveats\n\n- `connector.status_changed` fires beside this event with `state: degraded`; this event is the narrower signal that sales froze.\n- A Disaster Recovery incident opens too when the refusal warrants a replacement; see `recovery.incident_opened`.\n\n### Related events\n\n- `connector.outage_closed`: the outage ended.\n- `connector.status_changed`: the state transition behind it.",
                "summary": "A platform refused a project's live installation (token revoked or regenerated, bot deleted) and the connector entered an outage.",
                "tags": [
                    "connector.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "connector.outage_opened"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `connector.outage_opened` here.",
                                        "enum": [
                                            "connector.outage_opened"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector key."
                                            },
                                            "installation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The refused installation."
                                            },
                                            "outage_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The outage row; the same id closes in `connector.outage_closed`."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors top-level `project_id`."
                                            },
                                            "reason": {
                                                "type": "string",
                                                "description": "The connector's reason code for the refusal, the same code `state_reason` carries."
                                            },
                                            "started_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the refusal was recorded, which is where the outage's length is measured from."
                                            }
                                        },
                                        "required": [
                                            "connector",
                                            "installation_id",
                                            "outage_id",
                                            "project_id",
                                            "reason",
                                            "started_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "connector.outage_opened",
                                        "created_at": "2026-09-13T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "connector": "telegram",
                                            "installation_id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                            "outage_id": "9c1e4d2a-7b3f-4e8a-a2d1-5f6b7c8d9e0f",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "reason": "connector_api_unauthorized",
                                            "started_at": "2026-09-13T10:05:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-connector:view"
                ],
                "x-webhook-family": "connector"
            }
        },
        "connector.outage_closed": {
            "post": {
                "operationId": "webhook.connector.outage_closed",
                "description": "### When this fires\n\nAn open outage on a project's installation ended. `ended_by` says how: `recovered` when the probe found the installation healthy again or the creator reconnected it, `replaced` when another installation took over (a standby bot failed over, or the creator relinked a new bot), `uninstalled` when the creator removed the connector while the outage ran. Plans that were off sale return to sale at once.\n\nThe settlement follows from the queue and announces itself as `connector.outage_compensated`: invites that never reached a member during the outage are re-sent, and, when the outage lasted an hour or more, ended as `recovered` or `replaced`, and the project's **Outage Compensation** setting is on, every member whose paid access overlapped it has the outage's length banked on their purchase, one `member.access_extended` each. How the banked time reaches a member is described in [Connector outages](https://docs.subscriby.net/disaster-recovery/connector-outages).\n\n### Caveats\n\n- An `uninstalled` end compensates nobody: the uninstall's own preview and opt-ins settle what members get.\n- Outages shorter than an hour end with this event too, but earn no compensation.\n\n### Related events\n\n- `connector.outage_opened`: the outage began.\n- `connector.outage_compensated`: the settlement that follows this event.\n- `connector.connected`: a fresh connection that ends a `recovered` outage.\n- `connector.uninstalled`: the uninstall behind an `uninstalled` end.",
                "summary": "A connector outage ended: the installation answered again, another one took its place, or the creator uninstalled the connector.",
                "tags": [
                    "connector.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "connector.outage_closed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `connector.outage_closed` here.",
                                        "enum": [
                                            "connector.outage_closed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector key."
                                            },
                                            "duration_seconds": {
                                                "type": "integer",
                                                "description": "How long the outage ran, `ended_at` minus `started_at`."
                                            },
                                            "ended_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When it ended."
                                            },
                                            "ended_by": {
                                                "type": "string",
                                                "description": "How the outage ended.",
                                                "enum": [
                                                    "recovered",
                                                    "replaced",
                                                    "uninstalled"
                                                ]
                                            },
                                            "installation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The installation that was refused."
                                            },
                                            "outage_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The outage row, the same id `connector.outage_opened` carried."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors top-level `project_id`."
                                            },
                                            "started_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the outage began."
                                            }
                                        },
                                        "required": [
                                            "connector",
                                            "duration_seconds",
                                            "ended_at",
                                            "ended_by",
                                            "installation_id",
                                            "outage_id",
                                            "project_id",
                                            "started_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "connector.outage_closed",
                                        "created_at": "2026-09-13T13:20:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "connector": "telegram",
                                            "duration_seconds": 11700,
                                            "ended_at": "2026-09-13T13:20:00Z",
                                            "ended_by": "recovered",
                                            "installation_id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                            "outage_id": "9c1e4d2a-7b3f-4e8a-a2d1-5f6b7c8d9e0f",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "started_at": "2026-09-13T10:05:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-connector:view"
                ],
                "x-webhook-family": "connector"
            }
        },
        "connector.outage_compensated": {
            "post": {
                "operationId": "webhook.connector.outage_compensated",
                "description": "### When this fires\n\nOnce per outage, shortly after `connector.outage_closed`. The settlement runs from the queue: it first re-sends any invite that never reached a member while the connector was refusing the installation (`grants_replayed`), then, when the outage lasted an hour or more, ended as `recovered` or `replaced`, and the project's **Outage Compensation** setting is on, banks the outage's length on every live purchase that unlocks a place on that connector (`members_extended`, one `member.access_extended` each). The creator receives the same summary by email, on their connected account and in the notification centre; it is also the **Compensation** column of the Recovery History page.\n\n### Caveats\n\n- Fires with `members_extended: 0` when the outage was shorter than an hour, ended with an uninstall, or the project switched Outage Compensation off; the creator is not emailed in that case.\n- Money never moves: no charge, refund or renewal date changes. Recurring members receive the time at the end of their membership.\n\n### Related events\n\n- `member.access_extended`: one per compensated member.\n- `connector.outage_closed`: the outage this settles.",
                "summary": "A closed connector outage settled: how many members had time banked, how much each received, and how many invites lost during the outage were re-sent.",
                "tags": [
                    "connector.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "connector.outage_compensated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `connector.outage_compensated` here.",
                                        "enum": [
                                            "connector.outage_compensated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector that was refused."
                                            },
                                            "extended_seconds": {
                                                "type": "integer",
                                                "description": "The seconds each compensated member received; `0` when nobody was."
                                            },
                                            "grants_replayed": {
                                                "type": "integer",
                                                "description": "How many purchases had their invites re-sent because none reached the member during the outage."
                                            },
                                            "members_extended": {
                                                "type": "integer",
                                                "description": "How many members had the time banked."
                                            },
                                            "outage_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The outage row, the same id the opened and closed events carried."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors top-level `project_id`."
                                            }
                                        },
                                        "required": [
                                            "connector",
                                            "extended_seconds",
                                            "grants_replayed",
                                            "members_extended",
                                            "outage_id",
                                            "project_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "connector.outage_compensated",
                                        "created_at": "2026-09-13T13:21:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "connector": "telegram",
                                            "extended_seconds": 11700,
                                            "grants_replayed": 2,
                                            "members_extended": 18,
                                            "outage_id": "9c1e4d2a-7b3f-4e8a-a2d1-5f6b7c8d9e0f",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-connector:view"
                ],
                "x-webhook-family": "connector"
            }
        },
        "recovery.incident_opened": {
            "post": {
                "operationId": "webhook.recovery.incident_opened",
                "description": "### When this fires\n\nThe hourly probes check every bot, every channel and group a project sells, and the creator's own sign-in account. When one comes back banned, deleted, or stripped of the rights the bot needs, an **incident** opens in the recovery ledger and this event fires, once. A probe that finds the same broken thing on its next run reopens nothing and fires nothing; the incident stays open until it resolves. Undoing an account relink also opens an account incident (`reason: relink_disputed`) so support reviews the dispute.\n\n### Caveats\n\n- One event per incident. The ledger opens one incident per subject and keeps it open, so a subject that stays broken for a week fires this once, not hourly.\n- A restriction the platform reports as \"still reachable\" opens nothing: only a verdict that warrants a replacement counts. See [How detection works](https://docs.subscriby.net/disaster-recovery/how-detection-works).\n\n### Related events\n\n- `recovery.incident_resolved`: the same incident healing or being fixed.\n- `project.resource.status_changed`: the health verdict that precedes a resources incident.",
                "summary": "A health probe found the creator's sign-in account unreachable, a project's bot refused by the platform, or a channel or group gone or no longer administered.",
                "tags": [
                    "recovery.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "recovery.incident_opened"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `recovery.incident_opened` here.",
                                        "enum": [
                                            "recovery.incident_opened"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "incident_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The incident; read it with [the incident endpoint](https://docs.subscriby.net/api/v1/reference/disaster-recovery)."
                                            },
                                            "kind": {
                                                "type": "string",
                                                "description": "`account` (the creator's sign-in account), `bot` (a project's installation) or `resources` (a channel or group).",
                                                "enum": [
                                                    "account",
                                                    "bot",
                                                    "resources"
                                                ]
                                            },
                                            "connector": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector the broken thing lives on, such as `telegram`."
                                            },
                                            "project_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The project, for `bot` and `resources` incidents; null for `account`. The envelope `project_id` is null for an account incident too."
                                            },
                                            "resource_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The channel or group, for `resources` incidents; null otherwise."
                                            },
                                            "reason": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector's code for what it saw (`chat_not_found`, `bot_removed`, …); the API's `reason_label` puts it into words."
                                            },
                                            "detected_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the probe saw it."
                                            }
                                        },
                                        "required": [
                                            "incident_id",
                                            "kind",
                                            "connector",
                                            "project_id",
                                            "resource_id",
                                            "reason",
                                            "detected_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "recovery.incident_opened",
                                        "created_at": "2026-09-12T03:19:04Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "incident_id": "6f1e9b27-4c3a-4d58-9e02-b7a1c5d38f64",
                                            "kind": "resources",
                                            "connector": "telegram",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "reason": "chat_not_found",
                                            "detected_at": "2026-09-12T03:19:04Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-webhook-family": "recovery"
            }
        },
        "recovery.incident_resolved": {
            "post": {
                "operationId": "webhook.recovery.incident_resolved",
                "description": "### When this fires\n\nAn incident resolves in one of two ways: a later probe finds the account, bot or channel healthy again (the creator gave the bot its rights back, the platform lifted a restriction), or a recovery replaced the broken thing, in which case `resolved_by_operation_id` names it. Either way the incident row is marked resolved and this event fires once.\n\n### Caveats\n\n- A bot relink resolves every open bot incident the project had, whichever bot row each named: expect one event per incident.\n- Resolution says the ledger no longer sees a problem; it does not say members have been re-admitted. Follow `recovery.operation_completed` and the roll call for that.\n\n### Related events\n\n- `recovery.incident_opened`: how the incident began.\n- `recovery.operation_completed`: the recovery `resolved_by_operation_id` names.",
                "summary": "An open incident closed: a later probe found the thing healthy again, or a recovery replaced it.",
                "tags": [
                    "recovery.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "recovery.incident_resolved"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `recovery.incident_resolved` here.",
                                        "enum": [
                                            "recovery.incident_resolved"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "incident_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The incident that closed."
                                            },
                                            "kind": {
                                                "type": "string",
                                                "description": "What the incident was about.",
                                                "enum": [
                                                    "account",
                                                    "bot",
                                                    "resources"
                                                ]
                                            },
                                            "connector": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector the thing lives on."
                                            },
                                            "project_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The project, or null for an account incident."
                                            },
                                            "resource_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The channel or group, for `resources` incidents."
                                            },
                                            "resolved_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When it closed."
                                            },
                                            "resolved_by_operation_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The recovery that fixed it, or null when a probe simply found it healthy again."
                                            }
                                        },
                                        "required": [
                                            "incident_id",
                                            "kind",
                                            "connector",
                                            "project_id",
                                            "resource_id",
                                            "resolved_at",
                                            "resolved_by_operation_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "recovery.incident_resolved",
                                        "created_at": "2026-09-12T03:19:42Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "incident_id": "6f1e9b27-4c3a-4d58-9e02-b7a1c5d38f64",
                                            "kind": "resources",
                                            "connector": "telegram",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "resolved_at": "2026-09-12T03:19:42Z",
                                            "resolved_by_operation_id": "9a4d2e71-5b38-4c6f-8e12-3d7c9b0a5f21"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-webhook-family": "recovery"
            }
        },
        "recovery.operation_started": {
            "post": {
                "operationId": "webhook.recovery.operation_started",
                "description": "### When this fires\n\nThe moment a recovery is opened in the ledger: an account relink or a switch to the backup account, a bot replacement, or a channel swap. The row exists from this moment because it is the quota ledger too: the allowance is spent here, and given back only if the recovery fails before changing anything.\n\nA channel recovery absorbs every swap made inside its grace period into one operation, so a second channel swapped an hour after the first fires no second start; it fires `recovery.resource_replaced` under the same `operation_id`.\n\n### Caveats\n\n- Once per operation. Swaps absorbed into a running channel recovery fire no second start.\n- A recovery refused before the ledger row is written (quota spent, not the owner, plan lacks the feature) fires nothing.\n\n### Related events\n\n- `recovery.operation_completed`, `recovery.operation_failed`: how it ends.",
                "summary": "A recovery began: run by the creator, by the platform on their behalf, or on demand for a healthy resource.",
                "tags": [
                    "recovery.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "recovery.operation_started"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `recovery.operation_started` here.",
                                        "enum": [
                                            "recovery.operation_started"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "operation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The operation; read it with [the operation endpoint](https://docs.subscriby.net/api/v1/reference/disaster-recovery)."
                                            },
                                            "kind": {
                                                "type": "string",
                                                "description": "What the recovery acts on.",
                                                "enum": [
                                                    "account",
                                                    "bot",
                                                    "resources"
                                                ]
                                            },
                                            "connector": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector the recovery acts on."
                                            },
                                            "project_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The project, or null for an account recovery."
                                            },
                                            "automatic": {
                                                "type": "boolean",
                                                "description": "True when the platform ran it without the creator (automatic failover)."
                                            },
                                            "on_demand": {
                                                "type": "boolean",
                                                "description": "True for a Swap & Grant of a healthy resource, which spends no allowance."
                                            },
                                            "started_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When it began: the moment that counts for the rolling allowance."
                                            }
                                        },
                                        "required": [
                                            "operation_id",
                                            "kind",
                                            "connector",
                                            "project_id",
                                            "automatic",
                                            "on_demand",
                                            "started_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "recovery.operation_started",
                                        "created_at": "2026-09-12T03:19:10Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "operation_id": "9a4d2e71-5b38-4c6f-8e12-3d7c9b0a5f21",
                                            "kind": "resources",
                                            "connector": "telegram",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "automatic": true,
                                            "on_demand": false,
                                            "started_at": "2026-09-12T03:19:10Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-webhook-family": "recovery"
            }
        },
        "recovery.operation_completed": {
            "post": {
                "operationId": "webhook.recovery.operation_completed",
                "description": "### When this fires\n\nWhen the recovery's changes are in place: the creator signs in with the new account, the project's bot answers under the new token, the resource points at its replacement and re-admission has been queued. For a channel recovery this fires once, when the first swap completes; later swaps absorbed into the same operation fire `recovery.resource_replaced` only.\n\n### Caveats\n\n- Completion means the changes stand, not that every member is back in. Read the roll call at [the roll call endpoint](https://docs.subscriby.net/api/v1/reference/disaster-recovery) for that.\n- The creator also receives the recovery report by email a few minutes later, once the first re-admissions have landed.\n\n### Related events\n\n- `recovery.operation_reverted`: the creator undid it inside the window.\n- `recovery.resource_failed_over`, `recovery.resource_replaced`, `recovery.identity_relinked`: what the recovery did.",
                "summary": "A recovery finished and its changes stand; when it can be undone, the window is open from now.",
                "tags": [
                    "recovery.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "recovery.operation_completed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `recovery.operation_completed` here.",
                                        "enum": [
                                            "recovery.operation_completed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "operation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The operation."
                                            },
                                            "kind": {
                                                "type": "string",
                                                "description": "What the recovery acted on.",
                                                "enum": [
                                                    "account",
                                                    "bot",
                                                    "resources"
                                                ]
                                            },
                                            "connector": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector the recovery acted on."
                                            },
                                            "project_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The project, or null for an account recovery."
                                            },
                                            "automatic": {
                                                "type": "boolean",
                                                "description": "True when the platform ran it without the creator."
                                            },
                                            "on_demand": {
                                                "type": "boolean",
                                                "description": "True for a Swap & Grant of a healthy resource."
                                            },
                                            "started_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When it began."
                                            },
                                            "completed_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When its changes were in place."
                                            },
                                            "revert_window_ends_at": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "date-time",
                                                "description": "When the undo closes; null for a bot replacement, which cannot be undone."
                                            }
                                        },
                                        "required": [
                                            "operation_id",
                                            "kind",
                                            "connector",
                                            "project_id",
                                            "automatic",
                                            "on_demand",
                                            "started_at",
                                            "completed_at",
                                            "revert_window_ends_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "recovery.operation_completed",
                                        "created_at": "2026-09-12T03:19:42Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "operation_id": "9a4d2e71-5b38-4c6f-8e12-3d7c9b0a5f21",
                                            "kind": "resources",
                                            "connector": "telegram",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "automatic": true,
                                            "on_demand": false,
                                            "started_at": "2026-09-12T03:19:10Z",
                                            "completed_at": "2026-09-12T03:19:42Z",
                                            "revert_window_ends_at": "2026-09-13T03:19:42Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-webhook-family": "recovery"
            }
        },
        "recovery.operation_failed": {
            "post": {
                "operationId": "webhook.recovery.operation_failed",
                "description": "### When this fires\n\nThe recovery was opened in the ledger and then could not be carried out: the connector refused the new bot's credentials, the replacement chat could not be bound, the new account could not be linked. Nothing changed, so the operation is marked failed and its use of the rolling allowance is given back. The creator sees the refusal on the page that ran it; this event tells your systems.\n\n### Caveats\n\n- A swap that fails while a channel recovery is already absorbing swaps leaves that recovery standing: failing it would erase a swap that did happen. Only a recovery that failed on its first swap fires this.\n\n### Related events\n\n- `recovery.operation_started`: how it began.",
                "summary": "A recovery failed before changing anything; the allowance it spent is given back.",
                "tags": [
                    "recovery.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "recovery.operation_failed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `recovery.operation_failed` here.",
                                        "enum": [
                                            "recovery.operation_failed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "operation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The failed operation."
                                            },
                                            "kind": {
                                                "type": "string",
                                                "description": "What the recovery acted on.",
                                                "enum": [
                                                    "account",
                                                    "bot",
                                                    "resources"
                                                ]
                                            },
                                            "connector": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector the recovery acted on."
                                            },
                                            "project_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The project, or null for an account recovery."
                                            },
                                            "automatic": {
                                                "type": "boolean",
                                                "description": "True when the platform ran it without the creator."
                                            },
                                            "on_demand": {
                                                "type": "boolean",
                                                "description": "True for a Swap & Grant of a healthy resource."
                                            },
                                            "started_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When it began."
                                            },
                                            "failure_reason": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "What went wrong, as the ledger recorded it."
                                            }
                                        },
                                        "required": [
                                            "operation_id",
                                            "kind",
                                            "connector",
                                            "project_id",
                                            "automatic",
                                            "on_demand",
                                            "started_at",
                                            "failure_reason"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "recovery.operation_failed",
                                        "created_at": "2026-09-12T09:41:07Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "operation_id": "c2e8f1a9-6d47-4b3e-9f05-1a8d7c2e4b60",
                                            "kind": "bot",
                                            "connector": "telegram",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "automatic": false,
                                            "on_demand": false,
                                            "started_at": "2026-09-12T09:41:05Z",
                                            "failure_reason": "The platform refused the token."
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-webhook-family": "recovery"
            }
        },
        "recovery.operation_reverted": {
            "post": {
                "operationId": "webhook.recovery.operation_reverted",
                "description": "### When this fires\n\nInside the undo window the creator can put a swapped resource back onto its old chat, or move their sign-in back to the previous account. A channel recovery is undone one swap at a time, so this fires once per resource put back, with `resource_id`; the operation itself is marked reverted when its last standing swap is undone. An account relink is undone whole, in one event with `resource_id: null`, and opens an account incident (`relink_disputed`) so support reviews it.\n\n### Caveats\n\n- Undoing a swap re-admits every active member into the old chat again; expect a second round of `member.resource_*` events for the same members.\n- The undo window is 24 hours from completion by default; an attempt after it is refused and fires nothing.\n\n### Related events\n\n- `recovery.operation_completed`: the recovery being undone.\n- `recovery.incident_opened`: the disputed-relink incident an account undo opens.",
                "summary": "The creator undid a recovery inside its window: a swapped channel put back, or the previous sign-in account restored.",
                "tags": [
                    "recovery.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "recovery.operation_reverted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `recovery.operation_reverted` here.",
                                        "enum": [
                                            "recovery.operation_reverted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "operation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The operation being undone."
                                            },
                                            "kind": {
                                                "type": "string",
                                                "description": "`account` or `resources`; a bot replacement cannot be undone.",
                                                "enum": [
                                                    "account",
                                                    "resources"
                                                ]
                                            },
                                            "connector": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector the recovery acted on."
                                            },
                                            "project_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The project, or null for an account recovery."
                                            },
                                            "resource_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The resource put back onto its old chat; null for an account relink."
                                            },
                                            "reverted_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the undo happened."
                                            }
                                        },
                                        "required": [
                                            "operation_id",
                                            "kind",
                                            "connector",
                                            "project_id",
                                            "resource_id",
                                            "reverted_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "recovery.operation_reverted",
                                        "created_at": "2026-09-12T21:50:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "operation_id": "9a4d2e71-5b38-4c6f-8e12-3d7c9b0a5f21",
                                            "kind": "resources",
                                            "connector": "telegram",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "reverted_at": "2026-09-12T21:50:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-webhook-family": "recovery"
            }
        },
        "recovery.standby_registered": {
            "post": {
                "operationId": "webhook.recovery.standby_registered",
                "description": "### When this fires\n\nActive Disaster Prevention keeps two kinds of standby: a **standby bot** per project (a second token, stored without a webhook and probed like any bot) and a **standby chat** per resource (a spare channel or group the bot already administers, optionally mirrored). Registering either fires this event. Registering a new standby bot where one already existed also fires `recovery.standby_removed` with `reason: replaced` for the old one.\n\n### Caveats\n\n- The standby's own identifiers on the platform (the bot's token, the chat's id) are never in the payload.\n- Turning the mirror on or off later fires nothing; read the standby's state from the Prevention page.\n\n### Related events\n\n- `recovery.standby_removed`: the standby removed, replaced or used.\n- `recovery.resource_failed_over`: the standby chat doing its job.",
                "summary": "A spare bot is kept ready for a project, or a spare channel or group is kept ready for one resource.",
                "tags": [
                    "recovery.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "recovery.standby_registered"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `recovery.standby_registered` here.",
                                        "enum": [
                                            "recovery.standby_registered"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "standby": {
                                                "type": "string",
                                                "description": "`installation` for a standby bot, `resource` for a standby channel or group.",
                                                "enum": [
                                                    "installation",
                                                    "resource"
                                                ]
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The project."
                                            },
                                            "resource_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The resource the standby covers; null for a standby bot."
                                            },
                                            "connector": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector the standby lives on."
                                            },
                                            "mirror": {
                                                "type": "boolean",
                                                "description": "Whether posts are mirrored into the standby as they are made; always false for a standby bot."
                                            }
                                        },
                                        "required": [
                                            "standby",
                                            "project_id",
                                            "resource_id",
                                            "connector",
                                            "mirror"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "recovery.standby_registered",
                                        "created_at": "2026-09-01T14:22:09Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "standby": "resource",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "connector": "telegram",
                                            "mirror": true
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-webhook-family": "recovery"
            }
        },
        "recovery.standby_removed": {
            "post": {
                "operationId": "webhook.recovery.standby_removed",
                "description": "### When this fires\n\nA standby bot or standby chat leaves the reserve. `reason` says why: `removed` when the creator took it away, `replaced` when a new standby bot took the slot, `used` when a recovery consumed it (a bot relink from the standby, a one-click Swap & Grant onto the standby chat, or an automatic failover).\n\n### Caveats\n\n- A standby consumed by a recovery fires this beside the recovery's own events (`recovery.resource_failed_over` or `recovery.resource_replaced`, or the bot recovery's `recovery.operation_completed`); use `reason: used` to tell it from a deliberate removal.\n- The readiness checklist counts standbys, so a `removed` or `used` standby lowers the score until a new one is registered.\n\n### Related events\n\n- `recovery.standby_registered`: the standby being kept.",
                "summary": "A standby is no longer kept: the creator removed it, registered another in its place, or a recovery consumed it.",
                "tags": [
                    "recovery.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "recovery.standby_removed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `recovery.standby_removed` here.",
                                        "enum": [
                                            "recovery.standby_removed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "standby": {
                                                "type": "string",
                                                "description": "`installation` for a standby bot, `resource` for a standby channel or group.",
                                                "enum": [
                                                    "installation",
                                                    "resource"
                                                ]
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The project."
                                            },
                                            "resource_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The resource the standby covered; null for a standby bot."
                                            },
                                            "connector": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector the standby lived on."
                                            },
                                            "reason": {
                                                "type": "string",
                                                "description": "Why the standby left the reserve.",
                                                "enum": [
                                                    "removed",
                                                    "replaced",
                                                    "used"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "standby",
                                            "project_id",
                                            "resource_id",
                                            "connector",
                                            "reason"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "recovery.standby_removed",
                                        "created_at": "2026-09-12T03:19:42Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "standby": "resource",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "connector": "telegram",
                                            "reason": "used"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-webhook-family": "recovery"
            }
        },
        "recovery.installation_failed_over": {
            "post": {
                "operationId": "webhook.recovery.installation_failed_over",
                "description": "### When this fires\n\nA probe finds the platform refusing a project's live installation outright (the token revoked or regenerated, the bot deleted), the project has **Automatic Failover** switched on, a standby bot is registered and its last probe found it healthy, and the Project Bot allowance permits: the platform writes the standby's credentials into the project's installation, resolves the incident, closes the [connector outage](https://docs.subscriby.net/disaster-recovery/connector-outages) as `replaced`, and emails every member reachable by email their new link on the creator's behalf, at the per-email fee accepted when the switch was armed. This event fires the moment the switch completes; it sits under a recovery whose `recovery.operation_started` carries `automatic: true`, and the Project Bot allowance is spent exactly as by a manual relink.\n\n> The switch cannot be undone from the dashboard: the refused bot is gone as far as the platform is concerned. The standby slot is empty afterwards, so the creator is asked to register a new standby bot.\n\n### Caveats\n\n- Fires only for a platform-caused refusal. A rate limit or a passing API error marks the installation degraded but never triggers a failover.\n- When a condition fails (plan lapsed, no healthy standby, allowance spent, or the switch refused), nothing fires here; the creator receives *Automatic failover did not run for <project>'s bot* by email and on their connected account, and the incident stays open.\n\n### Related events\n\n- `recovery.resource_failed_over`: the channel-side twin.\n- `recovery.operation_started` / `recovery.operation_completed`: the recovery around the switch.\n- `connector.outage_closed`: the outage this switch ends as `replaced`.",
                "summary": "Automatic failover switched a project onto its standby bot without the creator, because the platform refused the live one: the bot-side twin of `recovery.resource_failed_over`.",
                "tags": [
                    "recovery.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "recovery.installation_failed_over"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `recovery.installation_failed_over` here.",
                                        "enum": [
                                            "recovery.installation_failed_over"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "connector": {
                                                "type": "string",
                                                "description": "The connector the installations live on."
                                            },
                                            "installation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The project's live installation, now carrying the standby's credentials; the same row as before."
                                            },
                                            "members_emailed": {
                                                "type": "integer",
                                                "description": "How many members were emailed their new link; `0` when nobody had a verified or billing address."
                                            },
                                            "operation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The recovery the switch ran under, marked automatic."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors top-level `project_id`."
                                            },
                                            "replaced_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the switch completed, as recorded in the ledger."
                                            }
                                        },
                                        "required": [
                                            "connector",
                                            "installation_id",
                                            "members_emailed",
                                            "operation_id",
                                            "project_id",
                                            "replaced_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "recovery.installation_failed_over",
                                        "created_at": "2026-09-14T03:19:42Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "connector": "telegram",
                                            "installation_id": "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40",
                                            "members_emailed": 214,
                                            "operation_id": "9a4d2e71-5b38-4c6f-8e12-3d7c9b0a5f21",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "replaced_at": "2026-09-14T03:19:41Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-webhook-family": "recovery"
            }
        },
        "recovery.resource_failed_over": {
            "post": {
                "operationId": "webhook.recovery.resource_failed_over",
                "description": "### When this fires\n\nA probe finds a channel gone or the bot removed from it, the project has **Automatic Failover** switched on, a healthy standby is linked, and the allowance permits: the platform points the resource at its standby, revokes the old links and queues every active member's re-admission, all without the creator. This event fires the moment the resource points at the standby; it sits under a recovery whose `recovery.operation_started` carries `automatic: true`.\n\n> **Members the bot cannot reach.** A failover emails the members the bot can no longer message, at a per-email fee the creator accepted when switching failover on. The roll call's `emailed` counter says how many.\n\n### Caveats\n\n- The standby that was consumed fires `recovery.standby_removed` with `reason: used` beside this event.\n- `project.resource.updated` also fires for the same resource with `changes.space_id`, as it does for any swap.\n\n### Related events\n\n- `recovery.resource_replaced`: the same swap made by the creator.\n- `recovery.operation_reverted`: the creator put the old chat back.",
                "summary": "Automatic failover swapped a banned channel or group for its standby without the creator: the failover you sleep through.",
                "tags": [
                    "recovery.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "recovery.resource_failed_over"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `recovery.resource_failed_over` here.",
                                        "enum": [
                                            "recovery.resource_failed_over"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "operation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The automatic recovery the swap ran under; its roll call says how re-admission is going."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The project."
                                            },
                                            "resource_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The resource, now pointing at the standby."
                                            },
                                            "resource_title": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The resource's title, as plans show it."
                                            },
                                            "connector": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector the chats live on."
                                            },
                                            "replaced_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the resource was re-pointed."
                                            }
                                        },
                                        "required": [
                                            "operation_id",
                                            "project_id",
                                            "resource_id",
                                            "resource_title",
                                            "connector",
                                            "replaced_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "recovery.resource_failed_over",
                                        "created_at": "2026-09-12T03:19:42Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "operation_id": "9a4d2e71-5b38-4c6f-8e12-3d7c9b0a5f21",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "resource_title": "Lounge",
                                            "connector": "telegram",
                                            "replaced_at": "2026-09-12T03:19:41Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-webhook-family": "recovery"
            }
        },
        "recovery.resource_replaced": {
            "post": {
                "operationId": "webhook.recovery.resource_replaced",
                "description": "### When this fires\n\nThe creator swaps a resource onto another chat: a replacement channel after a ban, the standby in one click, or a healthy resource moved to a new supergroup on demand (**Swap & Grant**, which spends no allowance). The resource is re-pointed, the old links revoked and every active member's re-admission queued. One event per resource swapped, each under the `operation_id` of the recovery absorbing it.\n\n### Caveats\n\n- A swap onto the standby chat also fires `recovery.standby_removed` with `reason: used`.\n- `project.resource.updated` fires for the same resource with `changes.space_id`, as it does for any swap.\n\n### Related events\n\n- `recovery.resource_failed_over`: the same swap made by the platform.\n- `recovery.operation_reverted`: the swap put back inside the window.",
                "summary": "The creator pointed a resource at a replacement channel or group: in a recovery after a ban, or on demand for a healthy resource.",
                "tags": [
                    "recovery.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "recovery.resource_replaced"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `recovery.resource_replaced` here.",
                                        "enum": [
                                            "recovery.resource_replaced"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "operation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The recovery the swap ran under; several swaps inside the grace period share one."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The project."
                                            },
                                            "resource_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The resource, now pointing at the replacement."
                                            },
                                            "resource_title": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The resource's title, as plans show it."
                                            },
                                            "connector": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector the chats live on."
                                            },
                                            "replaced_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the resource was re-pointed."
                                            },
                                            "on_demand": {
                                                "type": "boolean",
                                                "description": "True for a Swap & Grant of a healthy resource with no open incident, which spends no allowance."
                                            }
                                        },
                                        "required": [
                                            "operation_id",
                                            "project_id",
                                            "resource_id",
                                            "resource_title",
                                            "connector",
                                            "replaced_at",
                                            "on_demand"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "recovery.resource_replaced",
                                        "created_at": "2026-06-20T18:04:11Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "operation_id": "d4b7a2c9-1e58-4f36-8a0d-6c2e9b7f1a45",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "resource_id": "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6",
                                            "resource_title": "Members",
                                            "connector": "telegram",
                                            "replaced_at": "2026-06-20T18:04:11Z",
                                            "on_demand": true
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-webhook-family": "recovery"
            }
        },
        "recovery.identity_relinked": {
            "post": {
                "operationId": "webhook.recovery.identity_relinked",
                "description": "### When this fires\n\nAfter a ban on the creator's own account, recovery moves their Subscriby identity to another account on the connector: one they prove control of through a handshake, or the backup account they registered ahead of time (`from_backup: true`). Sign-in and alerts follow the new account at once; the previous one becomes the backup when a backup was switched in. This is an account-level event: `project_id` is null and it reaches the endpoints of the team the creator owns.\n\n### Caveats\n\n- The platform's own account identifiers (numeric ids, usernames) are deliberately absent; `identity_id` is the neutral id the rest of the API uses.\n- Every browser session of the creator is signed out by the relink. The undo, inside 24 hours, fires `recovery.operation_reverted` and opens a `relink_disputed` incident.\n\n### Related events\n\n- `recovery.operation_completed`: the same recovery, as an operation.\n- `recovery.operation_reverted`: the relink undone.",
                "summary": "The creator's sign-in account moved to another account on the connector: a newly detected one, or the backup switched in.",
                "tags": [
                    "recovery.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "recovery.identity_relinked"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `recovery.identity_relinked` here.",
                                        "enum": [
                                            "recovery.identity_relinked"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "operation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The account recovery."
                                            },
                                            "connector": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The connector both accounts live on."
                                            },
                                            "identity_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "Subscriby's id for the account now signing in, as [the me endpoint](https://docs.subscriby.net/api/v1/reference/me) lists it under `identities`; null when not yet recorded."
                                            },
                                            "display_name": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "The new account's display name, as the connector reported it."
                                            },
                                            "from_backup": {
                                                "type": "boolean",
                                                "description": "True when the registered backup account was switched in; false for a newly detected account."
                                            },
                                            "started_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the relink began."
                                            },
                                            "completed_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When sign-in moved."
                                            }
                                        },
                                        "required": [
                                            "operation_id",
                                            "connector",
                                            "identity_id",
                                            "display_name",
                                            "from_backup",
                                            "started_at",
                                            "completed_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "recovery.identity_relinked",
                                        "created_at": "2026-08-01T11:12:30Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "operation_id": "e7c3d9a1-2f64-4b08-9d5e-4a1b8c6f2d73",
                                            "connector": "telegram",
                                            "identity_id": "3c9e1f7a-8b25-4d60-a1f4-7e2c5b9d0a18",
                                            "display_name": "Ada (new)",
                                            "from_backup": false,
                                            "started_at": "2026-08-01T11:12:29Z",
                                            "completed_at": "2026-08-01T11:12:30Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-webhook-family": "recovery"
            }
        },
        "recovery.readiness_changed": {
            "post": {
                "operationId": "webhook.recovery.readiness_changed",
                "description": "### When this fires\n\nThe readiness checklist is what a creator has in place before anything happens: a second factor on the account, a backup sign-in account, and, per connector, the standbys, mirrors and automatic failover the platform can verify. Subscriby records the checklist's state after every event that could move a line (a standby registered or removed, a resource failed over or replaced, an account relinked, a connector installed, connected, disconnected or uninstalled) and once a night for the things that fire no event (a second factor, a passkey, a plan change). When the state differs from the last one recorded, this event fires with the checklist as it stands. Recording the same state twice fires nothing. Readiness is the creator's, not one project's, so the envelope `project_id` is null.\n\n### Caveats\n\n- The first checklist ever recorded for a creator fires nothing: there is no earlier state to differ from.\n- Reminders (a copy of the content elsewhere, a second human administrator) never appear here; they cannot be verified.\n- The labels, descriptions and fix links of each line are not in the payload; read them from [the readiness endpoint](https://docs.subscriby.net/api/v1/reference/disaster-recovery).\n\n### Related events\n\n- `recovery.standby_registered`: one of the changes that leads here.\n- `recovery.standby_removed`: another.",
                "summary": "A line of the Disaster Recovery readiness checklist changed state, and here is the whole checklist as it stands now.",
                "tags": [
                    "recovery.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "recovery.readiness_changed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `recovery.readiness_changed` here.",
                                        "enum": [
                                            "recovery.readiness_changed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "completed": {
                                                "type": "integer",
                                                "description": "Verifiable lines in place."
                                            },
                                            "total": {
                                                "type": "integer",
                                                "description": "Verifiable lines in all; reminders are not counted."
                                            },
                                            "complete": {
                                                "type": "boolean",
                                                "description": "Whether every verifiable line is in place."
                                            },
                                            "items": {
                                                "type": "array",
                                                "description": "Every verifiable line, in the order the dashboard shows them.",
                                                "items": {
                                                    "type": "object",
                                                    "properties": {
                                                        "key": {
                                                            "type": "string",
                                                            "description": "The line's key: `second_factor`, `backup_identity`, or a connector's own key such as `standby_spaces`."
                                                        },
                                                        "connector": {
                                                            "type": [
                                                                "string",
                                                                "null"
                                                            ],
                                                            "description": "The connector the line belongs to; `null` for the account-level lines."
                                                        },
                                                        "done": {
                                                            "type": "boolean",
                                                            "description": "Whether the line is in place."
                                                        },
                                                        "locked": {
                                                            "type": "boolean",
                                                            "description": "Whether the plan lacks the prevention feature the line needs."
                                                        }
                                                    },
                                                    "required": [
                                                        "key",
                                                        "connector",
                                                        "done",
                                                        "locked"
                                                    ]
                                                }
                                            },
                                            "changed": {
                                                "type": "array",
                                                "description": "The lines still open after the change, as `connector:key` (or `key` for an account-level line).",
                                                "items": {
                                                    "type": "string"
                                                }
                                            }
                                        },
                                        "required": [
                                            "completed",
                                            "total",
                                            "complete",
                                            "items",
                                            "changed"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "recovery.readiness_changed",
                                        "created_at": "2026-09-01T14:22:09Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "completed": 4,
                                            "total": 6,
                                            "complete": false,
                                            "items": [
                                                {
                                                    "key": "second_factor",
                                                    "connector": null,
                                                    "done": true,
                                                    "locked": false
                                                },
                                                {
                                                    "key": "backup_identity",
                                                    "connector": null,
                                                    "done": true,
                                                    "locked": false
                                                },
                                                {
                                                    "key": "standby_installation",
                                                    "connector": "telegram",
                                                    "done": true,
                                                    "locked": false
                                                },
                                                {
                                                    "key": "standby_spaces",
                                                    "connector": "telegram",
                                                    "done": false,
                                                    "locked": false
                                                },
                                                {
                                                    "key": "auto_failover",
                                                    "connector": "telegram",
                                                    "done": true,
                                                    "locked": false
                                                },
                                                {
                                                    "key": "live_mirror",
                                                    "connector": "telegram",
                                                    "done": false,
                                                    "locked": false
                                                }
                                            ],
                                            "changed": [
                                                "telegram:standby_spaces",
                                                "telegram:live_mirror"
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-recovery:view"
                ],
                "x-webhook-family": "recovery"
            }
        },
        "broadcast.queued": {
            "post": {
                "operationId": "webhook.broadcast.queued",
                "description": "### When this fires\n\nA broadcast began sending. The audience has been resolved to a concrete set of recipients and the first message is on its way.\n\nThis fires for broadcasts started **anywhere**: the dashboard, the bot, the REST API, a Zap or an n8n workflow. The event is emitted by the sending job itself rather than by each entry point, so every route announces a broadcast identically.\n\n> **This is the start, not the outcome.** Delivery runs at roughly 28 messages a second to stay inside the platform's rate limit, so a large broadcast is still sending long after this arrives. Subscribe to `broadcast.completed` for the tallies.\n\n### Caveats\n\n- `recipient_estimate` is the count **at the moment sending began**. Someone who joins mid-send is not included, and someone who blocks the bot mid-send is still counted here but will appear in `failed` on completion.\n- A member is only a recipient if they have a linked chat **on that project's bot**. A member with no chat, or one attached to a different bot, is silently excluded, which is why the estimate can be far lower than the project's member count.\n- The message body is **not** in the payload. Broadcasts are not persisted, and a body can be up to 4096 characters of arbitrary creator content; repeating it on every subscribed endpoint would leak it to integrations that only need to know a send happened.\n- If the audience resolves to zero recipients this still fires, immediately followed by `broadcast.completed` with `sent: 0`.\n\n### Related events\n\n- `broadcast.completed`: the outcome, with sent and failed tallies.\n- [Broadcasts](https://docs.subscriby.net/api/v1/reference/broadcasts): send one programmatically.",
                "summary": "A broadcast started sending, carrying the audience it resolved to and how many members it will reach.",
                "tags": [
                    "broadcast.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "broadcast.queued"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `broadcast.queued` here.",
                                        "enum": [
                                            "broadcast.queued"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Same project, repeated inside `data` so a consumer reading only the data object is self-sufficient."
                                            },
                                            "audience": {
                                                "type": "string",
                                                "description": "The segment addressed. One of the values in the audience segments table above."
                                            },
                                            "pass_window_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "Set only for the two single-window pass segments; `null` for every other audience."
                                            },
                                            "plan_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The plan the segment was narrowed to, if any. `null` when unnarrowed or when the segment cannot be narrowed."
                                            },
                                            "expiring_within_days": {
                                                "type": [
                                                    "integer",
                                                    "null"
                                                ],
                                                "description": "The horizon used, set only for `expiring_soon`; `null` for every other audience."
                                            },
                                            "recipient_estimate": {
                                                "type": "integer",
                                                "description": "How many members the resolved query matched at send time."
                                            }
                                        },
                                        "required": [
                                            "project_id",
                                            "audience",
                                            "pass_window_id",
                                            "plan_id",
                                            "expiring_within_days",
                                            "recipient_estimate"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "broadcast.queued",
                                        "created_at": "2026-09-01T10:30:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "audience": "customer",
                                            "pass_window_id": null,
                                            "plan_id": null,
                                            "expiring_within_days": null,
                                            "recipient_estimate": 128
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "broadcast:send"
                ],
                "x-webhook-family": "broadcast"
            }
        },
        "broadcast.completed": {
            "post": {
                "operationId": "webhook.broadcast.completed",
                "description": "### When this fires\n\nEvery recipient in a broadcast has been attempted and the send is over. The payload carries what actually happened.\n\n> `sent` means **the platform accepted the message**, not that a human read it. There is no read receipt, and a delivered message sitting in a muted chat counts as sent.\n\n### Reading the failure count\n\nA steady trickle of failures is normal and not actionable: the overwhelming majority are members who blocked the bot or deleted their account on the platform. Those are permanent; the sender detects them and stops retrying that recipient rather than burning attempts.\n\nWhat *is* worth alerting on is a sudden change in the ratio. `failed` climbing from ~2% to ~40% between two broadcasts usually means the bot's credentials were revoked or the bot was removed from the project's resources, not that forty percent of an audience left at once.\n\n`sent + failed` can be lower than the `recipient_estimate` reported by `broadcast.queued`: a recipient with no chat row is skipped without counting as either.\n\n### Caveats\n\n- Fires once per broadcast, at the end. A broadcast the platform rate-limits heavily can take minutes to finish; there is no progress event in between.\n- If the sending job is released and retried after a long rate-limit, the tallies count the **completed run** only.\n- A broadcast aborted before sending (no connected bot, an unknown audience, an empty body after sanitisation, or an audience the plan no longer includes) emits neither this nor `broadcast.queued`. Nothing was sent, so nothing is announced. The REST API refuses those cases up front with a `422` rather than accepting a send that will never leave.\n\n### Related events\n\n- `broadcast.queued`: the start, with the recipient estimate.",
                "summary": "A broadcast finished sending, carrying the delivered and failed tallies.",
                "tags": [
                    "broadcast.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "broadcast.completed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `broadcast.completed` here.",
                                        "enum": [
                                            "broadcast.completed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Same project, repeated inside `data` so a consumer reading only the data object is self-sufficient."
                                            },
                                            "audience": {
                                                "type": "string",
                                                "description": "The segment addressed."
                                            },
                                            "pass_window_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "Set only for the two single-window pass segments."
                                            },
                                            "plan_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The plan the segment was narrowed to, if any. `null` when unnarrowed."
                                            },
                                            "expiring_within_days": {
                                                "type": [
                                                    "integer",
                                                    "null"
                                                ],
                                                "description": "The horizon used, set only for `expiring_soon`."
                                            },
                                            "sent": {
                                                "type": "integer",
                                                "description": "Messages the platform accepted."
                                            },
                                            "failed": {
                                                "type": "integer",
                                                "description": "Recipients that could not be reached after the per-message retries were exhausted."
                                            }
                                        },
                                        "required": [
                                            "project_id",
                                            "audience",
                                            "pass_window_id",
                                            "plan_id",
                                            "expiring_within_days",
                                            "sent",
                                            "failed"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "broadcast.completed",
                                        "created_at": "2026-09-01T10:31:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "audience": "customer",
                                            "pass_window_id": null,
                                            "plan_id": null,
                                            "expiring_within_days": null,
                                            "sent": 126,
                                            "failed": 2
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "broadcast:send"
                ],
                "x-webhook-family": "broadcast"
            }
        },
        "access_code.generated": {
            "post": {
                "operationId": "webhook.access_code.generated",
                "description": "### When this fires\n\nA bulk-generation run for access codes completes. The batch is materialized in the database and is now redeemable. Batch-level only: this fires once per generation job, not per code. A 10,000-code batch produces one event.\n\n### Caveats\n\n- Codes themselves are never delivered through this event. The batch is delivered to the creator's chat on the connector as a CSV document or as one message per code, depending on the export type chosen at generation; to fetch them programmatically use [the access codes list](https://docs.subscriby.net/api/v1/reference/access-codes).\n- There is no batch identifier in the payload. Correlate a run by `plan_id` plus `created_at`, or list codes via the access codes endpoint.\n- Per-code redemption fires `access_code.redeemed`; per-code expiry fires `access_code.expired`.\n\n### Related events\n\n- `access_code.redeemed`: fires per code on redemption.\n- `access_code.expired`: fires per code on expiry.",
                "summary": "A bulk-generate job completes.",
                "tags": [
                    "access_code.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "access_code.generated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `access_code.generated` here.",
                                        "enum": [
                                            "access_code.generated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the codes are scoped to."
                                            },
                                            "plan_name": {
                                                "type": "string",
                                                "description": "Plan display name at generation time."
                                            },
                                            "count": {
                                                "type": "integer",
                                                "description": "Number of codes in the batch."
                                            },
                                            "expires_at": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "date-time",
                                                "description": "Common expiry timestamp for all codes in the batch. `null` when the batch was generated with no expiry."
                                            }
                                        },
                                        "required": [
                                            "plan_id",
                                            "plan_name",
                                            "count",
                                            "expires_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "access_code.generated",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "plan_name": "Premium Monthly",
                                            "count": 250,
                                            "expires_at": "2026-08-18T00:00:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-access-code:view"
                ],
                "x-webhook-family": "access_code"
            }
        },
        "access_code.redeemed": {
            "post": {
                "operationId": "webhook.access_code.redeemed",
                "description": "### When this fires\n\nA subscriber successfully redeems an access code. The placeholder subscription row created with that code at generation time is claimed for the subscriber and activated (or put into trial) on the associated plan.\n\n### Caveats\n\n- `access_code` is the complete code, not a masked fragment. It is already consumed and cannot be redeemed again, but treat it as a customer identifier and avoid forwarding it to systems you do not control.\n- Pairs with `subscription.created` and either `member.joined` or `member.trial_joined`, depending on whether the redeemed plan carries a trial.\n\n### Related events\n\n- `access_code.generated`: predecessor (batch-level).\n- `access_code.expired`: alternative outcome.",
                "summary": "A code is successfully redeemed by a subscriber.",
                "tags": [
                    "access_code.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "access_code.redeemed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `access_code.redeemed` here.",
                                        "enum": [
                                            "access_code.redeemed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscription now held by the subscriber. The row was created with the code at generation time, not by the redemption."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Project the redemption belongs to. Duplicates the envelope `project_id`."
                                            },
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the code was scoped to."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Subscriber's project-scoped user id."
                                            },
                                            "access_code": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The **full redeemed code** (UUID v4), not masked."
                                            }
                                        },
                                        "required": [
                                            "subscription_id",
                                            "project_id",
                                            "plan_id",
                                            "subscriber_id",
                                            "access_code"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "access_code.redeemed",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "access_code": "9c1a7b3f-5d80-4e62-a4f1-0b83d2e6c517"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-access-code:view"
                ],
                "x-webhook-family": "access_code"
            }
        },
        "access_code.expired": {
            "post": {
                "operationId": "webhook.access_code.expired",
                "description": "### When this fires\n\nAn access code passes its expiry without being redeemed. The placeholder subscription row holding it is hard-deleted immediately after this event is emitted.\n\nThe code string itself is **not** included on this event; only `access_code.redeemed` carries `access_code`. The placeholder row referenced by `subscription_id` is hard-deleted immediately after this event is emitted, so it will not resolve through the API.\n\n### Caveats\n\n- Expiry is detected by a sweep that runs every five minutes, so `created_at` trails `expired_at` by up to five minutes plus queue latency.\n- Large batches may produce a sustained burst of `access_code.expired` events when the batch hits its expiry. Plan capacity accordingly.\n- Codes that were already redeemed do not produce this event regardless of the batch's `expires_at`.\n\n### Related events\n\n- `access_code.redeemed`: alternative outcome.\n- `access_code.generated`: predecessor (batch-level).",
                "summary": "A code passes its expiry without redemption.",
                "tags": [
                    "access_code.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "access_code.expired"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `access_code.expired` here.",
                                        "enum": [
                                            "access_code.expired"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "plan_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Plan the code was scoped to."
                                            },
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Placeholder subscription row that held the unredeemed code."
                                            },
                                            "expired_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the code became unredeemable."
                                            }
                                        },
                                        "required": [
                                            "plan_id",
                                            "subscription_id",
                                            "expired_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "access_code.expired",
                                        "created_at": "2026-08-18T00:04:12Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "expired_at": "2026-08-18T00:00:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "project-access-code:view"
                ],
                "x-webhook-family": "access_code"
            }
        },
        "support.conversation.opened": {
            "post": {
                "operationId": "webhook.support.conversation.opened",
                "description": "### When this fires\n\nA member sends your project bot a message it does not recognise as a command, an access code, or an answer the bot was waiting for, and they have no conversation on that channel yet. Subscriby creates the conversation and emits this event, immediately followed by `support.message.received` for the message itself.\n\nThe message can be text, a photo, a document, a voice note or any other supported media. A bare photo with no caption opens a conversation just as text does.\n\nIt does **not** fire when:\n\n- The member already has a conversation on that channel, even a resolved one. A resolved thread reopens and raises `support.conversation.reopened` instead.\n- The message was a recognised bot command, or an answer the bot was waiting for during a guided setup step.\n- The member is blocked, or has tripped the inbound rate limit.\n- Support is switched off for the project.\n\n> This fires **once per member, per channel, ever**. It is a \"new contact\" signal, not a \"new question\" signal. For every question a member asks, listen to `support.message.received`.\n\n### Caveats\n\n- The payload carries no message body and no member name. Fetch them with [the conversation messages endpoint](https://docs.subscriby.net/api/v1/reference/support-inbox).\n- The member may be a **lead** rather than a subscriber. Anyone who can reach the bot can open a conversation, including someone who has never paid: `data.subscriber_id` resolves to a project user whose status may be `lead`.\n- Opening a conversation is not the same as the creator being notified. Notification is throttled to one bot DM per conversation per five minutes, so a burst of messages produces one ping but many events.\n\n### Related events\n\n- `support.message.received`: fires alongside this event, for the message itself.\n- `support.conversation.reopened`: the returning-member counterpart.",
                "summary": "A member starts their first support conversation on a channel.",
                "tags": [
                    "support.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "support.conversation.opened"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `support.conversation.opened` here.",
                                        "enum": [
                                            "support.conversation.opened"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "conversation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The new conversation. Use it against the support API to read the message."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors the envelope `project_id`."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member's project-scoped user id."
                                            },
                                            "channel": {
                                                "type": "string",
                                                "description": "The key of the connector the member wrote through (`telegram` for the Telegram connector). A member who writes through two connectors has two conversations."
                                            }
                                        },
                                        "required": [
                                            "conversation_id",
                                            "project_id",
                                            "subscriber_id",
                                            "channel"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "support.conversation.opened",
                                        "created_at": "2026-08-20T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "conversation_id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "channel": "telegram"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "support-conversation:view"
                ],
                "x-webhook-family": "support"
            }
        },
        "support.conversation.assigned": {
            "post": {
                "operationId": "webhook.support.conversation.assigned",
                "description": "### When this fires\n\nA conversation's assignee changes: it is handed to a team member from the dashboard inbox, the REST API, Zapier, or n8n, or an existing assignment is cleared.\n\n> Clearing an assignment fires this same event with `data.assigned_to_user_id: null`. There is no separate \"unassigned\" event; branch on the null.\n\n### Caveats\n\n- `assigned_to_user_id` is a **team member's** user id, an account with dashboard access, not the member's `subscriber_id`. The two are different namespaces.\n- Assignment is advisory. It does not restrict who may reply; anyone on the team with `support-conversation:update` still can.\n- Re-assigning to the same person fires the event again. Deduplicate on `id` if you are posting notifications.\n\n### Related events\n\n- `support.conversation.resolved`: the usual next step once the assignee has answered.\n- `support.message.received`: what typically prompts an assignment.",
                "summary": "A support conversation is handed to a team member, or its assignment cleared.",
                "tags": [
                    "support.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "support.conversation.assigned"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `support.conversation.assigned` here.",
                                        "enum": [
                                            "support.conversation.assigned"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "conversation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The conversation whose assignee changed."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors the envelope `project_id`."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member the conversation belongs to."
                                            },
                                            "assigned_to_user_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "The team member now responsible. **`null` means the assignment was cleared.**"
                                            }
                                        },
                                        "required": [
                                            "conversation_id",
                                            "project_id",
                                            "subscriber_id",
                                            "assigned_to_user_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "support.conversation.assigned",
                                        "created_at": "2026-08-20T10:09:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "conversation_id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "assigned_to_user_id": "4b7c9d21-3e58-4f16-8a02-6d9e5c1b7f34"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "support-conversation:view"
                ],
                "x-webhook-family": "support"
            }
        },
        "support.conversation.resolved": {
            "post": {
                "operationId": "webhook.support.conversation.resolved",
                "description": "### When this fires\n\nA conversation is marked resolved from the dashboard inbox, the REST API, Zapier, n8n, or the [`resolve_support_conversation`](https://docs.subscriby.net/mcp/v1/tools/support/resolve-support-conversation) MCP tool.\n\n> Resolving is not closing. The thread and its full history are kept, and it reopens by itself the moment the member writes again, which raises `support.conversation.reopened`.\n\n### Caveats\n\n- Resolving does not notify the member. If you want them to know the matter is closed, send a reply before resolving.\n- The event fires even if the conversation was already resolved. Deduplicate on `id`.\n- A resolved conversation still counts toward the member's history and still appears under the **Resolved** tab in the inbox; it is filtered out of the open queue, not deleted.\n\n### Related events\n\n- `support.conversation.reopened`: what happens when the member writes back.\n- `support.message.sent`: the reply that usually precedes resolving.",
                "summary": "A support conversation is marked resolved and leaves the open queue.",
                "tags": [
                    "support.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "support.conversation.resolved"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `support.conversation.resolved` here.",
                                        "enum": [
                                            "support.conversation.resolved"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "conversation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The conversation that was resolved."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors the envelope `project_id`."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member the conversation belongs to."
                                            }
                                        },
                                        "required": [
                                            "conversation_id",
                                            "project_id",
                                            "subscriber_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "support.conversation.resolved",
                                        "created_at": "2026-08-20T10:12:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "conversation_id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "support-conversation:view"
                ],
                "x-webhook-family": "support"
            }
        },
        "support.conversation.reopened": {
            "post": {
                "operationId": "webhook.support.conversation.reopened",
                "description": "### When this fires\n\nA conversation that was `resolved` goes back to `open`. Two paths:\n\n1. **The member writes again.** Their inbound message reopens the thread automatically, raising this event alongside `support.message.received`. This is the usual cause.\n2. **A creator reopens it explicitly**: from the dashboard inbox, with `POST /v1/support/conversations/{id}/reopen`, with the `reopen_support_conversation` MCP tool, or through the Reopen Support Conversation action in Zapier and n8n.\n\nIt does **not** fire when:\n\n- The member writes into a thread that is already `open`, `pending` or `snoozed`. Only a resolved thread reopens on inbound. A creator reopening a thread by hand fires the event whatever the thread's previous status was, including `open`.\n- The member is **blocked**. A blocked contact's message is dropped and cannot push their thread back into the queue.\n- The member edited an older message rather than sending a new one.\n\n> The common path here is **not** a creator reopening a thread by hand; it is a member writing back after you resolved it. If you page an on-call rota on anything in this family, this is the event that catches the \"we thought this was done\" case.\n\n### Caveats\n\n- On the member-writes-back path this event and `support.message.received` fire for the same action. If you post to a channel on both, you will post twice; pick one as the trigger and enrich from the API.\n- The payload does not say which path caused the reopen. Compare the newest message's `direction` over the API if it matters: `inbound` means the member came back, `outbound` or no new message means a creator reopened it by hand.\n- `first_response_at` is **not** reset by a reopen. It is stamped once, for the first human reply ever in that thread, so SLA reporting across a reopen needs message timestamps rather than that field.\n\n### Related events\n\n- `support.conversation.resolved`: the state this event reverses.\n- `support.message.received`: fires alongside on the member-writes-back path.",
                "summary": "A resolved support conversation becomes active again.",
                "tags": [
                    "support.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "support.conversation.reopened"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `support.conversation.reopened` here.",
                                        "enum": [
                                            "support.conversation.reopened"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "conversation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The conversation that reopened."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors the envelope `project_id`."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member the conversation belongs to."
                                            }
                                        },
                                        "required": [
                                            "conversation_id",
                                            "project_id",
                                            "subscriber_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "support.conversation.reopened",
                                        "created_at": "2026-08-20T14:30:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "conversation_id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "support-conversation:view"
                ],
                "x-webhook-family": "support"
            }
        },
        "support.conversation.blocked": {
            "post": {
                "operationId": "webhook.support.conversation.blocked",
                "description": "### When this fires\n\nA creator blocks the member behind a support conversation:\n\n- **Dashboard**: **Block member** in the thread's header menu in the support inbox.\n- **REST**: `POST /v1/support/conversations/{conversation}/block`.\n- **MCP**: the `block_support_contact` tool.\n\nIt does **not** fire when:\n\n- The conversation is already blocked. Blocking twice writes nothing the second time and emits nothing; the call is idempotent.\n- A member is banned from the project. That is `member.banned`, a different mechanism that removes access rather than silencing a thread.\n- The member's message is dropped because of rate limiting. Flood protection is automatic and raises no event.\n\n> A block lives on the **conversation**, not the member. It silences their support traffic only: the member keeps their subscription, their access and every other interaction with the bot, and they are given no indication that anything changed.\n\n### Caveats\n\n- Blocking does not resolve the thread. Its `status` is whatever it was (`open`, `pending`, `snoozed` or `resolved`) and stays that way until someone changes it. If you keep a queue in sync, treat a blocked thread as one that will receive no new inbound messages, not as a closed one.\n- From this moment the member's messages are dropped at ingestion. No `support.message.received` fires for them, and a blocked member's message cannot reopen a resolved thread, so no `support.conversation.reopened` fires either.\n- The block is scoped to this thread. There is one conversation per member per channel, so a member who also writes in over another channel has a separate thread with its own block state.\n- The member's history is untouched. Every message they sent before the block stays readable over the API and in the dashboard.\n\n### Related events\n\n- `support.conversation.unblocked`: the block is lifted.\n- `support.message.received`: what stops arriving for this member while the block is in place.\n- `member.banned`: removing a member's access, which is not what a block does.",
                "summary": "A creator silences a member's support messages.",
                "tags": [
                    "support.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "support.conversation.blocked"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `support.conversation.blocked` here.",
                                        "enum": [
                                            "support.conversation.blocked"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "conversation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The conversation that was blocked. [The conversation endpoint](https://docs.subscriby.net/api/v1/reference/support-inbox) now reports `blocked: true`."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors the envelope `project_id`."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member whose support messages are now dropped."
                                            }
                                        },
                                        "required": [
                                            "conversation_id",
                                            "project_id",
                                            "subscriber_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "support.conversation.blocked",
                                        "created_at": "2026-09-06T09:30:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "conversation_id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "support-conversation:view"
                ],
                "x-webhook-family": "support"
            }
        },
        "support.conversation.unblocked": {
            "post": {
                "operationId": "webhook.support.conversation.unblocked",
                "description": "### When this fires\n\nA creator lifts the block on a support conversation:\n\n- **Dashboard**: **Unblock member** in the thread's header menu in the support inbox.\n- **REST**: `POST /v1/support/conversations/{conversation}/unblock`.\n- **MCP**: the `unblock_support_contact` tool.\n\nIt does **not** fire when:\n\n- The conversation was not blocked. Unblocking an unblocked thread writes nothing and emits nothing; the call is idempotent.\n- A banned member is unbanned. That is `member.unbanned`; a ban and a support block are independent, and lifting one does not touch the other.\n\n> Unblocking restores the flow of new messages. It does not replay anything the member sent while blocked; those messages were dropped at ingestion and are gone.\n\n### Caveats\n\n- The thread's `status` is unchanged by an unblock, exactly as it was by the block. A thread that was `resolved` when blocked is still `resolved` now; the member's next message will reopen it and raise `support.conversation.reopened` as usual.\n- Nothing is replayed. If the member wrote in while blocked, those messages produced no `support.message.received` and never will.\n- The payload does not say how long the block lasted. Pair this event's `created_at` with the matching `support.conversation.blocked` by `conversation_id` if you report on it.\n\n### Related events\n\n- `support.conversation.blocked`: the state this event reverses.\n- `support.conversation.reopened`: what the member's next message may now trigger.",
                "summary": "A creator lets a silenced member's support messages through again.",
                "tags": [
                    "support.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "support.conversation.unblocked"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `support.conversation.unblocked` here.",
                                        "enum": [
                                            "support.conversation.unblocked"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "conversation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The conversation that was unblocked. [The conversation endpoint](https://docs.subscriby.net/api/v1/reference/support-inbox) now reports `blocked: false`."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors the envelope `project_id`."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member whose support messages are accepted again."
                                            }
                                        },
                                        "required": [
                                            "conversation_id",
                                            "project_id",
                                            "subscriber_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "support.conversation.unblocked",
                                        "created_at": "2026-09-06T11:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "conversation_id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "support-conversation:view"
                ],
                "x-webhook-family": "support"
            }
        },
        "support.message.received": {
            "post": {
                "operationId": "webhook.support.message.received",
                "description": "### When this fires\n\nEvery time a member sends an inbound message that lands in the support inbox, including the very first one, which also raises `support.conversation.opened`.\n\nThis is the workhorse of the family. If you are routing member questions into a helpdesk, an ops channel or an on-call rota, this is the event to subscribe to.\n\nIt does **not** fire when:\n\n- The text was a recognised bot command, or an answer the bot was waiting for mid-setup.\n- The member is blocked. Their messages are dropped without a trace in the inbox.\n- The member has tripped the inbound rate limit. Excess messages are dropped silently rather than queued.\n- The member **edited** an earlier message. The stored message is updated in place and no new event fires.\n\n> The message body is **not** in the payload. Webhook deliveries are logged and retried, and member text does not belong in a delivery log. Fetch it with [the conversation messages endpoint](https://docs.subscriby.net/api/v1/reference/support-inbox).\n\n### Caveats\n\n- **No body, no name, no file ids.** Everything human-readable is behind the API on purpose. Platform file ids are effectively credentials for downloading the file and are never sent in a webhook.\n- An **album** (several photos sent together) arrives as one event per part, each with its own `message_id`. They share a `media_group_id` visible through the API, not in the payload.\n- A captioned photo has `type: \"photo\"`, and the caption is the message body; it is not a separate text message.\n- A caption that starts with `/` is parsed as a bot command upstream and never reaches the inbox.\n\n### Related events\n\n- `support.conversation.opened`: fires alongside on the member's first message.\n- `support.message.sent`: your side of the exchange.\n- `support.conversation.reopened`: fires alongside when the message revives a resolved thread.",
                "summary": "A member sends a message into a support conversation.",
                "tags": [
                    "support.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "support.message.received"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `support.message.received` here.",
                                        "enum": [
                                            "support.message.received"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "message_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The stored message."
                                            },
                                            "conversation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Thread the message belongs to."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors the envelope `project_id`."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member's project-scoped user id."
                                            },
                                            "type": {
                                                "type": "string",
                                                "description": "What kind of message arrived.",
                                                "enum": [
                                                    "text",
                                                    "photo",
                                                    "video",
                                                    "audio",
                                                    "voice",
                                                    "document",
                                                    "sticker",
                                                    "animation",
                                                    "location",
                                                    "contact"
                                                ]
                                            },
                                            "has_attachments": {
                                                "type": "boolean",
                                                "description": "Whether the message carried a structured attachment. True for media, and also for `location` and `contact`, whose attachment rows carry `file_id: null` and no file to fetch. Check `data.type` before assuming a download."
                                            }
                                        },
                                        "required": [
                                            "message_id",
                                            "conversation_id",
                                            "project_id",
                                            "subscriber_id",
                                            "type",
                                            "has_attachments"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "support.message.received",
                                        "created_at": "2026-08-20T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "message_id": "6c18f7a3-2e95-4d60-b47a-c093e5182b7f",
                                            "conversation_id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "type": "text",
                                            "has_attachments": false
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "support-conversation:view"
                ],
                "x-webhook-family": "support"
            }
        },
        "support.message.sent": {
            "post": {
                "operationId": "webhook.support.message.sent",
                "description": "### When this fires\n\nA creator or team member replies to a member, from any surface: the dashboard inbox, the relay DM on the connector, the REST API, or the [`reply_support_conversation`](https://docs.subscriby.net/mcp/v1/tools/support/reply-support-conversation) MCP tool.\n\nIt does **not** fire when:\n\n- The reply was recorded as an **internal note**. Notes are private remarks for your team, are never delivered to the member, and raise no event.\n- An automated acknowledgement goes out. The project's auto-reply is a system message, not a creator reply.\n\n> This fires when the reply is **recorded and queued**, not when the member receives it. Delivery happens on a queue and can still fail; a member who has blocked the bot is unreachable. Read `delivery_status` from the support API for the outcome.\n\n### Caveats\n\n- The payload does not say **who** replied. Read `author_user_id` from [the conversation messages endpoint](https://docs.subscriby.net/api/v1/reference/support-inbox) if you need to attribute it to a specific team member.\n- The member sees the reply prefixed with the project's support name, so it reads as coming from a person rather than from the bot. That prefix is added at delivery and is not part of the stored body.\n- Pairing this with `support.message.received` gives you first-response time. The conversation's own `first_response_at` is stamped only once, on the first human reply, which is the more reliable SLA measure.\n\n### Related events\n\n- `support.message.received`: the member's side.\n- `support.conversation.resolved`: usually the next step after a reply.",
                "summary": "A reply to a member is recorded and queued for delivery.",
                "tags": [
                    "support.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "support.message.sent"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `support.message.sent` here.",
                                        "enum": [
                                            "support.message.sent"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "message_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The stored reply."
                                            },
                                            "conversation_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Thread the reply belongs to."
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors the envelope `project_id`."
                                            },
                                            "subscriber_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The member the reply is addressed to."
                                            },
                                            "type": {
                                                "type": "string",
                                                "description": "`text`, or the media kind when the reply carried an attachment."
                                            }
                                        },
                                        "required": [
                                            "message_id",
                                            "conversation_id",
                                            "project_id",
                                            "subscriber_id",
                                            "type"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "support.message.sent",
                                        "created_at": "2026-08-20T10:07:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "message_id": "6c18f7a3-2e95-4d60-b47a-c093e5182b7f",
                                            "conversation_id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45",
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "type": "text"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "support-conversation:view"
                ],
                "x-webhook-family": "support"
            }
        },
        "support.canned_reply.created": {
            "post": {
                "operationId": "webhook.support.canned_reply.created",
                "description": "### When this fires\n\nA creator saves a new reusable reply on a project:\n\n- **Dashboard**: **Saved Replies → Add Reply** from the support inbox.\n- **REST**: `POST /v1/projects/{project}/support/canned-replies`.\n- **MCP**: the `create_canned_reply` tool.\n\nIt does **not** fire when:\n\n- A saved reply is inserted into a conversation. Using a snippet is just composing a message; the reply that goes out raises `support.message.sent` like any other.\n- The save is rejected. A duplicate `shortcut` on the same project, or a body outside its limits, fails validation and writes nothing.\n\n> The dashboard calls these **Saved Replies**; the event keeps the `canned_reply` name. The snapshot carries the snippet's title, shortcut and position but **never its body**. Fetch that with [the canned reply endpoint](https://docs.subscriby.net/api/v1/reference/support-inbox) if you mirror the picker somewhere else.\n\n### Caveats\n\n- The `body` is the one thing a consumer usually wants and the one thing not sent. This matches the family rule that no `support.*` payload carries message text; read it over the API.\n- `shortcut` is unique per project, so it doubles as a stable handle for the snippet in a mirror, but it is optional and editable, so key on `id`.\n- `sort_order` is not a dense sequence. Several snippets can share a value; the dashboard orders ties by creation.\n\n### Related events\n\n- `support.canned_reply.updated`: the snippet is reworded, given a new shortcut or moved.\n- `support.canned_reply.deleted`: the snippet is removed from the picker.",
                "summary": "A saved reply is added to a project's support inbox.",
                "tags": [
                    "support.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "support.canned_reply.created"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `support.canned_reply.created` here.",
                                        "enum": [
                                            "support.canned_reply.created"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "canned_reply": {
                                                "type": "object",
                                                "description": "The new snippet: `id`, `title`, `shortcut`, `sort_order` only. No `body`.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Saved reply identifier."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "The label shown in the picker, 2–80 characters."
                                                    },
                                                    "shortcut": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "The token typed in the composer to expand the snippet: letters, digits, dashes and underscores, up to 30 characters, stored without a leading slash. `null` when none was set."
                                                    },
                                                    "sort_order": {
                                                        "type": "integer",
                                                        "description": "Position in the picker, `0`–`999`. Defaults to `0` when the request omits it."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "title",
                                                    "shortcut",
                                                    "sort_order"
                                                ]
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors the envelope `project_id`."
                                            }
                                        },
                                        "required": [
                                            "canned_reply",
                                            "project_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "support.canned_reply.created",
                                        "created_at": "2026-09-06T09:40:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "canned_reply": {
                                                "id": "c2f8e6a1-7d34-4b9e-a05c-3e1f9b7d2a68",
                                                "title": "Opening hours",
                                                "shortcut": "hours",
                                                "sort_order": 1
                                            },
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "support-conversation:view"
                ],
                "x-webhook-family": "support"
            }
        },
        "support.canned_reply.updated": {
            "post": {
                "operationId": "webhook.support.canned_reply.updated",
                "description": "### When this fires\n\nA creator edits an existing saved reply and at least one of `title`, `body`, `shortcut` or `sort_order` is different afterwards:\n\n- **Dashboard**: **Saved Replies → edit → Update Reply** from the support inbox.\n- **REST**: `PATCH /v1/projects/{project}/support/canned-replies/{reply}`. Fields you omit keep their stored value.\n- **MCP**: the `update_canned_reply` tool.\n\nIt does **not** fire when:\n\n- Nothing changed. The action compares before and after and skips the event when the two match.\n- The snippet is inserted into a conversation. Using a saved reply is composing a message, and the message raises `support.message.sent`.\n- The edit is rejected (a `shortcut` already used by another snippet on the project, or a body outside its 2–4000 character limits): nothing is written.\n\n> One save is one event, and `changes` lists only the fields that actually differ. A save that changes nothing (the dashboard's **Update Reply** with no edits, or a `PATCH` that re-sends the stored values) emits nothing.\n\n### Caveats\n\n- The snapshot never carries the body, but `changes.body` does when the body is what changed: `from` and `to` hold the full old and new text. This is the creator's own template text, not a member's message, so the family's rule that member text never enters a delivery log still holds. If you would rather not receive it, it only appears on edits to the body itself.\n- `changes` can report `body`, which the snapshot omits, and the snapshot carries `id`, which `changes` never does. Use both halves: `canned_reply` for the current state, `changes` for what to diff.\n- Reordering snippets in the dashboard can raise one event per snippet whose `sort_order` moved. Expect a burst with `changes: { sort_order: … }` and nothing else.\n\n### Related events\n\n- `support.canned_reply.created`: the snippet's first appearance.\n- `support.canned_reply.deleted`: its removal.",
                "summary": "A saved reply's title, body, shortcut or position changes.",
                "tags": [
                    "support.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "support.canned_reply.updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `support.canned_reply.updated` here.",
                                        "enum": [
                                            "support.canned_reply.updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "canned_reply": {
                                                "type": "object",
                                                "description": "Post-update snapshot: `id`, `title`, `shortcut`, `sort_order` only. No `body`.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Saved reply identifier."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Picker label after the change."
                                                    },
                                                    "shortcut": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Expansion token after the change, or `null` when cleared."
                                                    },
                                                    "sort_order": {
                                                        "type": "integer",
                                                        "description": "Picker position after the change."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "title",
                                                    "shortcut",
                                                    "sort_order"
                                                ]
                                            },
                                            "changes": {
                                                "type": "object",
                                                "description": "The fields that changed. Keys are one or more of `title`, `body`, `shortcut`, `sort_order`; values are before/after pairs. Never empty.",
                                                "properties": {
                                                    "title": {
                                                        "type": "object",
                                                        "description": "Present only when the title changed.",
                                                        "properties": {
                                                            "from": {
                                                                "type": "string",
                                                                "description": "Previous title."
                                                            },
                                                            "to": {
                                                                "type": "string",
                                                                "description": "New title."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    },
                                                    "body": {
                                                        "type": "object",
                                                        "description": "Present only when the body changed.",
                                                        "properties": {
                                                            "from": {
                                                                "type": "string",
                                                                "description": "Previous body text."
                                                            },
                                                            "to": {
                                                                "type": "string",
                                                                "description": "New body text, up to 4000 characters."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    },
                                                    "shortcut": {
                                                        "type": "object",
                                                        "description": "Present only when the shortcut changed.",
                                                        "properties": {
                                                            "from": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "Previous shortcut."
                                                            },
                                                            "to": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "New shortcut, or `null` when cleared."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    },
                                                    "sort_order": {
                                                        "type": "object",
                                                        "description": "Present only when the position changed.",
                                                        "properties": {
                                                            "from": {
                                                                "type": "integer",
                                                                "description": "Previous position."
                                                            },
                                                            "to": {
                                                                "type": "integer",
                                                                "description": "New position."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    }
                                                }
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors the envelope `project_id`."
                                            }
                                        },
                                        "required": [
                                            "canned_reply",
                                            "changes",
                                            "project_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "support.canned_reply.updated",
                                        "created_at": "2026-09-06T09:45:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "canned_reply": {
                                                "id": "c2f8e6a1-7d34-4b9e-a05c-3e1f9b7d2a68",
                                                "title": "Opening hours",
                                                "shortcut": "open",
                                                "sort_order": 1
                                            },
                                            "changes": {
                                                "shortcut": {
                                                    "from": "hours",
                                                    "to": "open"
                                                }
                                            },
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "support-conversation:view"
                ],
                "x-webhook-family": "support"
            }
        },
        "support.canned_reply.deleted": {
            "post": {
                "operationId": "webhook.support.canned_reply.deleted",
                "description": "### When this fires\n\nA creator removes a saved reply from a project:\n\n- **Dashboard**: the delete action on a snippet under **Saved Replies** in the support inbox.\n- **REST**: `DELETE /v1/projects/{project}/support/canned-replies/{reply}`.\n- **MCP**: the `delete_canned_reply` tool.\n\nIt does **not** fire when:\n\n- The snippet was already gone. A second delete writes nothing and emits nothing.\n- A message composed from the snippet is deleted or edited in a conversation. The saved reply is a template; what was sent is a separate message with its own lifecycle.\n- The project itself is deleted. Its snippets go with it under `project.deleted` without a per-snippet event.\n\n> This is the final event for the given `canned_reply.id`. The snapshot is taken just before the row goes, so the payload still names what disappeared even though the canned reply endpoint now returns `404`.\n\n### Caveats\n\n- The body is gone with the row and was never in any event, so a mirror that wants to keep the text must have fetched it while the snippet existed.\n- The freed `shortcut` can be reused by a new snippet straight away. Key a mirror on `id`, not on the shortcut.\n- Remaining snippets are not renumbered. Their `sort_order` values are unchanged and no `updated` events follow a delete.\n\n### Related events\n\n- `support.canned_reply.created`: the snippet's first appearance.\n- `support.canned_reply.updated`: edits between creation and this event.",
                "summary": "A saved reply is removed from a project's support inbox.",
                "tags": [
                    "support.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "support.canned_reply.deleted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `support.canned_reply.deleted` here.",
                                        "enum": [
                                            "support.canned_reply.deleted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "canned_reply": {
                                                "type": "object",
                                                "description": "Snapshot taken before the delete: `id`, `title`, `shortcut`, `sort_order` only. No `body`.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "Saved reply identifier. No longer resolvable over the API."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Picker label at the moment of deletion."
                                                    },
                                                    "shortcut": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Expansion token at the moment of deletion, or `null` if none was set."
                                                    },
                                                    "sort_order": {
                                                        "type": "integer",
                                                        "description": "Picker position at the moment of deletion."
                                                    }
                                                },
                                                "required": [
                                                    "id",
                                                    "title",
                                                    "shortcut",
                                                    "sort_order"
                                                ]
                                            },
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors the envelope `project_id`."
                                            }
                                        },
                                        "required": [
                                            "canned_reply",
                                            "project_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "support.canned_reply.deleted",
                                        "created_at": "2026-09-06T09:50:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "canned_reply": {
                                                "id": "c2f8e6a1-7d34-4b9e-a05c-3e1f9b7d2a68",
                                                "title": "Opening hours",
                                                "shortcut": "open",
                                                "sort_order": 1
                                            },
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "support-conversation:view"
                ],
                "x-webhook-family": "support"
            }
        },
        "support.settings.updated": {
            "post": {
                "operationId": "webhook.support.settings.updated",
                "description": "### When this fires\n\nA creator saves the project's support settings and at least one of the five visible settings is different afterwards:\n\n- **Dashboard**: **Support Settings → Save** from the support inbox.\n- **REST**: `PATCH /v1/projects/{project}/support/settings`. Fields you omit keep their stored value.\n- **MCP**: the `update_support_settings` tool.\n\nIt does **not** fire when:\n\n- Nothing changed. Saving the form untouched, or a `PATCH` that re-sends the stored values, writes nothing and emits nothing. Blank strings normalise to `null` before the comparison, so clearing an already-empty `agent_name` is not a change.\n- The bot links or unlinks the relay chat. That handshake changes the relay chat id, which is not one of the five settings this event covers.\n- A member's message is auto-acknowledged. Sending the `auto_reply` text is a message, not a settings change, and raises nothing in this family.\n\n> The relay chat id (the chat or forum group the bot forwards member messages to) is **never** in this payload. It is an identifier the bot's linking handshake writes, not a setting a creator types, and no surface can change it through this path.\n\n### Caveats\n\n- Subscribing needs `support-conversation:view`, but **making** the change needs the project update permission (`project:update` on a token), because the settings are columns on the project rather than on the inbox. A token that can read support threads can hear about settings changes it could not have made.\n- `settings` is always the full post-save state, even when only one key changed. You can overwrite a cached copy wholesale and use `changes` purely for \"what to announce\".\n- `auto_reply` is creator-authored template text and does appear in both `settings` and `changes`; it is the message members receive, not a message a member sent, so the family's rule about member text is intact.\n- Switching `relay_mode` to `forum_group` does not by itself link a group. The project bot links a group when the creator adds it to a supergroup with Topics enabled as an administrator, and confirms by DM; until that happens, notifications have nowhere to go and member messages reach only the dashboard inbox.\n\n### Related events\n\n- `support.conversation.opened`: the traffic these settings govern.\n- `project.updated`: other project-level edits, which never include the support columns.",
                "summary": "A project's support inbox settings change.",
                "tags": [
                    "support.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "support.settings.updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `support.settings.updated` here.",
                                        "enum": [
                                            "support.settings.updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "project_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Mirrors the envelope `project_id`."
                                            },
                                            "settings": {
                                                "type": "object",
                                                "description": "The complete settings after the save: the same five keys [the support settings endpoint](https://docs.subscriby.net/api/v1/reference/support-inbox) returns, minus its `project_id` and `updated_at`.",
                                                "properties": {
                                                    "enabled": {
                                                        "type": "boolean",
                                                        "description": "Whether member messages are accepted at all. When `false`, an unrecognised message gets the bot's not-understood reply instead of opening a thread."
                                                    },
                                                    "relay_mode": {
                                                        "type": "string",
                                                        "description": "How the creator is told a member wrote in: not at all, as a DM from the bot, or as a topic in a linked forum group.",
                                                        "enum": [
                                                            "none",
                                                            "owner_dm",
                                                            "forum_group"
                                                        ]
                                                    },
                                                    "agent_name": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "The name shown above each reply so it reads as a person, up to 60 characters. `null` means the project name is used."
                                                    },
                                                    "auto_reply": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "The acknowledgement sent at most once per hour when a member writes in, up to 1000 characters. `null` means nothing is sent."
                                                    },
                                                    "notify_email": {
                                                        "type": "boolean",
                                                        "description": "Whether a backlog warning is also emailed alongside the connector notification."
                                                    }
                                                },
                                                "required": [
                                                    "enabled",
                                                    "relay_mode",
                                                    "agent_name",
                                                    "auto_reply",
                                                    "notify_email"
                                                ]
                                            },
                                            "changes": {
                                                "type": "object",
                                                "description": "The settings that changed. Keys are one or more of the five `settings` keys; values are before/after pairs. Never empty.",
                                                "properties": {
                                                    "enabled": {
                                                        "type": "object",
                                                        "description": "Present only when the switch flipped.",
                                                        "properties": {
                                                            "from": {
                                                                "type": "boolean",
                                                                "description": "Previous value."
                                                            },
                                                            "to": {
                                                                "type": "boolean",
                                                                "description": "New value."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    },
                                                    "relay_mode": {
                                                        "type": "object",
                                                        "description": "Present only when the relay mode changed.",
                                                        "properties": {
                                                            "from": {
                                                                "type": "string",
                                                                "description": "Previous relay mode.",
                                                                "enum": [
                                                                    "none",
                                                                    "owner_dm",
                                                                    "forum_group"
                                                                ]
                                                            },
                                                            "to": {
                                                                "type": "string",
                                                                "description": "New relay mode.",
                                                                "enum": [
                                                                    "none",
                                                                    "owner_dm",
                                                                    "forum_group"
                                                                ]
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    },
                                                    "agent_name": {
                                                        "type": "object",
                                                        "description": "Present only when the display name changed.",
                                                        "properties": {
                                                            "from": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "Previous display name."
                                                            },
                                                            "to": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "New display name, or `null` when cleared."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    },
                                                    "auto_reply": {
                                                        "type": "object",
                                                        "description": "Present only when the acknowledgement text changed.",
                                                        "properties": {
                                                            "from": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "Previous acknowledgement text."
                                                            },
                                                            "to": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "New acknowledgement text, or `null` when cleared."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    },
                                                    "notify_email": {
                                                        "type": "object",
                                                        "description": "Present only when the switch flipped.",
                                                        "properties": {
                                                            "from": {
                                                                "type": "boolean",
                                                                "description": "Previous value."
                                                            },
                                                            "to": {
                                                                "type": "boolean",
                                                                "description": "New value."
                                                            }
                                                        },
                                                        "required": [
                                                            "from",
                                                            "to"
                                                        ]
                                                    }
                                                }
                                            }
                                        },
                                        "required": [
                                            "project_id",
                                            "settings",
                                            "changes"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "support.settings.updated",
                                        "created_at": "2026-09-06T10:02:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                        "data": {
                                            "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
                                            "settings": {
                                                "enabled": true,
                                                "relay_mode": "owner_dm",
                                                "agent_name": "Team Research Premium",
                                                "auto_reply": null,
                                                "notify_email": false
                                            },
                                            "changes": {
                                                "relay_mode": {
                                                    "from": "none",
                                                    "to": "owner_dm"
                                                },
                                                "agent_name": {
                                                    "from": null,
                                                    "to": "Team Research Premium"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "support-conversation:view"
                ],
                "x-webhook-family": "support"
            }
        },
        "team.created": {
            "post": {
                "operationId": "webhook.team.created",
                "description": "### When this fires\n\nA team is created, including the personal team created alongside a new account. Creating additional teams requires Growth tier or higher.\n\n> **Not currently delivered.** Endpoints are scoped to a team, and an endpoint cannot exist for a team before that team does, so this event is not currently delivered to any subscriber. Poll [the teams list](https://docs.subscriby.net/api/v1/reference/teams) if you need to observe team creation.\n\n### Caveats\n\n- Creating an additional team requires the Growth tier or above. The personal team created at registration is not gated, so the event is emitted on every tier; it is the subsequent, explicit team creations that Free and Starter cannot reach.\n- The personal team created with the account emits this too. Nothing in the payload distinguishes it from an explicitly created team.\n\n### Related events\n\n- `team.deleted`: terminal state.\n- `team.member.invited`: typical follow-up.",
                "summary": "A team is created, including the personal team created alongside a new account.",
                "tags": [
                    "team.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "team.created"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `team.created` here.",
                                        "enum": [
                                            "team.created"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "team_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Team identifier."
                                            },
                                            "name": {
                                                "type": "string",
                                                "description": "Display name."
                                            },
                                            "owner_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "User id of the team owner."
                                            }
                                        },
                                        "required": [
                                            "team_id",
                                            "name",
                                            "owner_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "team.created",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                            "name": "Research Team",
                                            "owner_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "team:view"
                ],
                "x-webhook-family": "team"
            }
        },
        "team.updated": {
            "post": {
                "operationId": "webhook.team.updated",
                "description": "### When this fires\n\nA team's name changes. That is the whole of it today: `name` is the only mutable field on a team. Ownership does not transfer, and the tier a team sits on is a property of the owner's billing rather than of the team, so neither shows up here.\n\n> **Fires however the rename happened.** The team model dispatches this from its own event map, not from any one code path. A rename through [the REST endpoint](https://docs.subscriby.net/api/v1/reference/teams), through the `update_team` MCP tool, or from a console fix that went near either, all emit it identically. The dashboard has no rename control today, so the API and MCP are the only routes.\n\n### Caveats\n\n- **No before value.** The payload carries the name the team has now, not the one it had. If your mirror needs the old name, keep it from the previous event or read it before applying.\n- **A team has no code.** Unlike roles and groups, teams are addressed only by `team_id`, so a rename never breaks a reference.\n- Renaming has no effect on membership, roles, groups, projects or billing.\n\n### Related events\n\n- `team.created`: predecessor.\n- `team.deleted`: terminal state.",
                "summary": "A team is renamed.",
                "tags": [
                    "team.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "team.updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `team.updated` here.",
                                        "enum": [
                                            "team.updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "team_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The team that was renamed."
                                            },
                                            "name": {
                                                "type": "string",
                                                "description": "The **new** name. The previous one is not carried."
                                            },
                                            "owner_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The team owner. Unchanged by a rename; included so a consumer can attribute the team without a second call."
                                            }
                                        },
                                        "required": [
                                            "team_id",
                                            "name",
                                            "owner_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "team.updated",
                                        "created_at": "2026-08-31T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                            "name": "Northwind Studios",
                                            "owner_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "team:view"
                ],
                "x-webhook-family": "team"
            }
        },
        "team.deleted": {
            "post": {
                "operationId": "webhook.team.deleted",
                "description": "### When this fires\n\nA team is deleted. Projects that were scoped to it are detached: their `team_id` becomes null and they keep running under the owner's personal scope. Nothing about them is deleted and no `project.*` event fires.\n\n> **Not delivered to the deleted team's endpoints.** An endpoint is scoped to a team, and deleting the team removes its endpoints in the same operation, so this event is not currently delivered to endpoints belonging to the deleted team.\n\n### Caveats\n\n- A team that still has collaborators cannot be deleted: the membership table's foreign key restricts it. Every `team.member.removed` for the team therefore precedes `team.deleted`, never follows it.\n- The only team that cannot be deleted is your last one; an owner with more than one team may delete whichever they like, including the team created with the account. Nothing in the payload distinguishes them.\n\n### Related events\n\n- `team.created`: first event in the lifecycle.",
                "summary": "A team is deleted; its projects are detached, not deleted.",
                "tags": [
                    "team.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "team.deleted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `team.deleted` here.",
                                        "enum": [
                                            "team.deleted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "team_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Team that was deleted."
                                            },
                                            "name": {
                                                "type": "string",
                                                "description": "Last-known display name."
                                            }
                                        },
                                        "required": [
                                            "team_id",
                                            "name"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "team.deleted",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                            "name": "Research Team"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "team:view"
                ],
                "x-webhook-family": "team"
            }
        },
        "team.member.invited": {
            "post": {
                "operationId": "webhook.team.member.invited",
                "description": "### When this fires\n\nA team owner or manager invites a collaborator by email. The collaborator becomes a member only once they accept and `team.member.joined` fires. The invitee has not yet accepted at this point.\n\n### Caveats\n\n- An invitation can be revoked without producing a follow-up event in this family. Invitations do not expire: a pending one stands until it is accepted or withdrawn.\n- The collaborator does not have access until they accept; expect `team.member.joined`.\n\n### Related events\n\n- `team.member.joined`: fires on acceptance.\n- `team.member.removed`: fires only if the collaborator accepts and is later removed. Withdrawing the invitation itself emits nothing.",
                "summary": "An invitation is issued to a new collaborator.",
                "tags": [
                    "team.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "team.member.invited"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `team.member.invited` here.",
                                        "enum": [
                                            "team.member.invited"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "team_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Team the invitation is for."
                                            },
                                            "email": {
                                                "type": "string",
                                                "format": "email",
                                                "description": "Email address the invitation was sent to."
                                            },
                                            "role_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Role assigned to the collaborator on acceptance."
                                            },
                                            "role_code": {
                                                "type": "string",
                                                "description": "Stable role code (for example `manager`, `viewer`)."
                                            }
                                        },
                                        "required": [
                                            "team_id",
                                            "email",
                                            "role_id",
                                            "role_code"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "team.member.invited",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                            "email": "collaborator@example.com",
                                            "role_id": "d05e1a83-7c46-4f29-b613-8ae407c9d251",
                                            "role_code": "manager"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "team:view"
                ],
                "x-webhook-family": "team"
            }
        },
        "team.member.joined": {
            "post": {
                "operationId": "webhook.team.member.joined",
                "description": "### When this fires\n\nAn invited collaborator accepts and joins the team.\n\n### Caveats\n\n- The collaborator's role was determined at invitation time; see the matching `team.member.invited` event for the role.\n- A user can belong to multiple teams; this event is scoped per (team, user).\n\n### Related events\n\n- `team.member.invited`: predecessor.\n- `team.member.role_changed`: typical follow-up over time.",
                "summary": "An invited collaborator accepts and joins.",
                "tags": [
                    "team.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "team.member.joined"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `team.member.joined` here.",
                                        "enum": [
                                            "team.member.joined"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "team_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Team the collaborator joined."
                                            },
                                            "user_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "User id of the collaborator."
                                            }
                                        },
                                        "required": [
                                            "team_id",
                                            "user_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "team.member.joined",
                                        "created_at": "2026-05-18T10:30:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                            "user_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "team:view"
                ],
                "x-webhook-family": "team"
            }
        },
        "team.member.removed": {
            "post": {
                "operationId": "webhook.team.member.removed",
                "description": "### When this fires\n\nA team owner removes a collaborator. There is no self-service leave, so this event always represents an action taken by the owner.\n\n### Caveats\n\n- Removal detaches the team membership row and nothing else. Roles are team-scoped, so there is no per-project assignment to revoke, and group memberships are left in place: re-adding the same user restores their old group memberships.\n\n### Related events\n\n- `team.member.invited`: predecessor in the lifecycle.\n- `team.member.joined`: predecessor.",
                "summary": "A collaborator is removed from a team by its owner.",
                "tags": [
                    "team.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "team.member.removed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `team.member.removed` here.",
                                        "enum": [
                                            "team.member.removed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "team_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Team the collaborator was on."
                                            },
                                            "user_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "User id of the removed collaborator."
                                            }
                                        },
                                        "required": [
                                            "team_id",
                                            "user_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "team.member.removed",
                                        "created_at": "2026-05-22T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                            "user_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "team:view"
                ],
                "x-webhook-family": "team"
            }
        },
        "team.member.role_changed": {
            "post": {
                "operationId": "webhook.team.member.role_changed",
                "description": "### When this fires\n\nA collaborator's role within the team changes: promoted, demoted, or moved between custom roles. Nothing in Subscriby fired this before the team member role endpoint existed; that endpoint and the `update_team_member_role` MCP tool are what make it fire.\n\n### Caveats\n\n- For ability detail behind a role id, listen for `role.updated` or pull the role definition from the API.\n- This event covers the team-level role on the membership pivot only. Groups carry permissions rather than roles, so a change to group membership emits `group.members_synced` instead and never this event.\n\n### Related events\n\n- `team.member.joined`: predecessor in the lifecycle.\n- `role.updated`: emits when the role definition itself changes.",
                "summary": "A collaborator's role within a team changes.",
                "tags": [
                    "team.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "team.member.role_changed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `team.member.role_changed` here.",
                                        "enum": [
                                            "team.member.role_changed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "team_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Team the collaborator belongs to."
                                            },
                                            "user_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "User id of the collaborator whose role changed."
                                            },
                                            "role_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "Currently always `null`: the team's pivot role is not carried on this event. Read the role from [the team member endpoint](https://docs.subscriby.net/api/v1/reference/team-members)."
                                            }
                                        },
                                        "required": [
                                            "team_id",
                                            "user_id",
                                            "role_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "team.member.role_changed",
                                        "created_at": "2026-05-22T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                            "user_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "role_id": null
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "team:view"
                ],
                "x-webhook-family": "team"
            }
        },
        "role.created": {
            "post": {
                "operationId": "webhook.role.created",
                "description": "### When this fires\n\nAny member of the team (or a token carrying `role:create`) creates a new role. It also fires three times when a team is first seeded, once for each default role.\n\n### Caveats\n\n- The full ability list is not embedded in this event; fetch the role from the API for complete detail.\n- The three default roles a new team is seeded with (`admin`, `manager`, `viewer`) emit this event too, one per role, at the moment the team is created.\n\n### Related events\n\n- `role.updated`: subsequent edits.\n- `role.deleted`: terminal state.",
                "summary": "A new role is created within a team.",
                "tags": [
                    "role.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "role.created"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `role.created` here.",
                                        "enum": [
                                            "role.created"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "team_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Team the role belongs to."
                                            },
                                            "role_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Role identifier."
                                            },
                                            "code": {
                                                "type": "string",
                                                "description": "Stable, human-readable role code."
                                            },
                                            "name": {
                                                "type": "string",
                                                "description": "Display name."
                                            }
                                        },
                                        "required": [
                                            "team_id",
                                            "role_id",
                                            "code",
                                            "name"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "role.created",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                            "role_id": "d05e1a83-7c46-4f29-b613-8ae407c9d251",
                                            "code": "plan-editor",
                                            "name": "Plan Editor"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "role:view"
                ],
                "x-webhook-family": "role"
            }
        },
        "role.updated": {
            "post": {
                "operationId": "webhook.role.updated",
                "description": "### When this fires\n\nA role's name, description, or permission set is saved, including the default `admin`, `manager` and `viewer` roles. The event is emitted on every save, even one that changes nothing, so treat it as \"the role was written\" rather than \"the role changed\".\n\n### Caveats\n\n- This event fires on both name changes and ability-set changes; fetch the role from the API to determine what actually changed.\n- Collaborators currently holding the role pick up the new abilities immediately on next request.\n\n### Related events\n\n- `role.created`: predecessor.\n- `team.member.role_changed`: fires when a collaborator's role assignment changes (different surface).",
                "summary": "A role's name or abilities change.",
                "tags": [
                    "role.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "role.updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `role.updated` here.",
                                        "enum": [
                                            "role.updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "team_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Team the role belongs to."
                                            },
                                            "role_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Role identifier."
                                            },
                                            "code": {
                                                "type": "string",
                                                "description": "Stable role code (immutable across renames)."
                                            },
                                            "name": {
                                                "type": "string",
                                                "description": "Updated display name."
                                            }
                                        },
                                        "required": [
                                            "team_id",
                                            "role_id",
                                            "code",
                                            "name"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "role.updated",
                                        "created_at": "2026-05-22T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                            "role_id": "d05e1a83-7c46-4f29-b613-8ae407c9d251",
                                            "code": "plan-editor",
                                            "name": "Plan Editor"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "role:view"
                ],
                "x-webhook-family": "role"
            }
        },
        "role.deleted": {
            "post": {
                "operationId": "webhook.role.deleted",
                "description": "### When this fires\n\nA role that no collaborator currently holds is deleted. A role still assigned to someone cannot be deleted at all; the database refuses it.\n\n### Caveats\n\n- Deleting is restricted to the role's creator, unless the caller owns the team: a team owner can delete any role in their team, including the default `admin`, `manager` and `viewer` roles. The dashboard hides the action for roles you did not create; the API and MCP surfaces do not.\n\n### Related events\n\n- `role.created`: first event in the lifecycle.\n- `team.member.role_changed`: emits for explicit role re-assignments.",
                "summary": "A role is deleted. Only roles no collaborator currently holds can be deleted.",
                "tags": [
                    "role.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "role.deleted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `role.deleted` here.",
                                        "enum": [
                                            "role.deleted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "team_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Team the role belonged to."
                                            },
                                            "role_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Role that was deleted."
                                            },
                                            "code": {
                                                "type": "string",
                                                "description": "Last-known stable role code."
                                            }
                                        },
                                        "required": [
                                            "team_id",
                                            "role_id",
                                            "code"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "role.deleted",
                                        "created_at": "2026-05-22T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                            "role_id": "d05e1a83-7c46-4f29-b613-8ae407c9d251",
                                            "code": "plan-editor"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "role:view"
                ],
                "x-webhook-family": "role"
            }
        },
        "group.created": {
            "post": {
                "operationId": "webhook.group.created",
                "description": "### When this fires\n\nA team owner or manager creates a new group. Groups bundle collaborators behind a shared permission set: several people in a team can be in the same group, and someone can be in more than one.\n\n### Caveats\n\n- Neither the permission set nor the member list is embedded in this event; read [the group endpoint](https://docs.subscriby.net/api/v1/reference/groups) for the group's current permissions, and expect `group.members_synced` when people are put into it.\n- Changing who is in the group emits `group.members_synced`, not this event; `team.member.role_changed` covers a member's team role and is unrelated to groups.\n\n### Related events\n\n- `group.updated`: subsequent edits.\n- `group.deleted`: terminal state.",
                "summary": "A new team group is created.",
                "tags": [
                    "group.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "group.created"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `group.created` here.",
                                        "enum": [
                                            "group.created"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "team_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Team that owns the group."
                                            },
                                            "group_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Group identifier."
                                            },
                                            "code": {
                                                "type": "string",
                                                "description": "Stable, human-readable group code."
                                            },
                                            "name": {
                                                "type": "string",
                                                "description": "Display name."
                                            }
                                        },
                                        "required": [
                                            "team_id",
                                            "group_id",
                                            "code",
                                            "name"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "group.created",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                            "group_id": "1f68d92a-04c5-4e83-97b1-3d6a05e2f847",
                                            "code": "core-community",
                                            "name": "Core Community"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "group:view"
                ],
                "x-webhook-family": "group"
            }
        },
        "group.updated": {
            "post": {
                "operationId": "webhook.group.updated",
                "description": "### When this fires\n\nA group is renamed, or the permissions attached to it are replaced. Who is *in* the group is a separate event, `group.members_synced`, because the two changes have different consequences. A rename is cosmetic; changing the permission set silently re-scopes everyone already in the group.\n\n### Caveats\n\n- **The permission set is not in the payload**, so this event tells you a group changed without telling you into what. Read [the group endpoint](https://docs.subscriby.net/api/v1/reference/groups) for the current permissions.\n- **Permissions replace, they do not merge.** An update that sends `permissions` sets them to exactly that list, so everyone in the group can gain and lose access in the same event.\n- `code` is immutable, so a rename never breaks a reference held elsewhere.\n- Membership is untouched here. See `group.members_synced`.\n\n### Related events\n\n- `group.members_synced`: who is in the group changed.\n- `group.created`: predecessor.\n- `group.deleted`: terminal state.",
                "summary": "A group is renamed or its permission set replaced.",
                "tags": [
                    "group.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "group.updated"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `group.updated` here.",
                                        "enum": [
                                            "group.updated"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "team_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Team that owns the group."
                                            },
                                            "group_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Group identifier."
                                            },
                                            "code": {
                                                "type": "string",
                                                "description": "Stable group code (immutable across renames)."
                                            },
                                            "name": {
                                                "type": "string",
                                                "description": "Updated display name."
                                            }
                                        },
                                        "required": [
                                            "team_id",
                                            "group_id",
                                            "code",
                                            "name"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "group.updated",
                                        "created_at": "2026-05-22T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                            "group_id": "1f68d92a-04c5-4e83-97b1-3d6a05e2f847",
                                            "code": "core-community",
                                            "name": "Core Community"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "group:view"
                ],
                "x-webhook-family": "group"
            }
        },
        "group.members_synced": {
            "post": {
                "operationId": "webhook.group.members_synced",
                "description": "### When this fires\n\nThe membership of a group is replaced and the result differs from what was there before, via [the group members endpoint](https://docs.subscriby.net/api/v1/reference/groups) or the dashboard's group editor.\n\nA group carries permissions, so who is in it decides who can do what. Until this event existed, renaming a group announced itself with `group.updated` while changing who it granted access to announced nothing at all; an integration mirroring access control could see the label change and miss the membership.\n\n> **A no-op sync is silent.** Syncing the same set that is already there emits nothing. This event means the membership actually moved, so receiving one always implies at least one id in `added_ids` or `removed_ids`.\n\n### Why the deltas are in the payload\n\nAn access-control mirror needs to know who *lost* the group, and diffing two snapshots on the far side is work it should not have to do: it requires having stored the previous state, and gets the answer wrong the first time it sees a group. `added_ids` and `removed_ids` are computed where the truth is, from the membership read immediately before the write and the list written immediately after it.\n\n`member_ids` is still there for consumers that would rather replace their copy than apply a patch. Both are consistent with each other.\n\n### Caveats\n\n- **This is a replace, not an add.** Anyone absent from the request is removed. An empty list empties the group.\n- **Permissions are not in the payload.** What the group grants is a property of the group, not of this event; read it from [the group endpoint](https://docs.subscriby.net/api/v1/reference/groups) if your mirror needs the effective permission set.\n- **Users, not projects.** A group clusters collaborators. It is not a way to bundle projects.\n- Removal from a group does not remove anyone from the team.\n\n### Related events\n\n- `group.updated`: the group was renamed or re-permissioned.\n- `group.created`: predecessor.\n- `group.deleted`: terminal state; everyone loses what it granted at once.",
                "summary": "The set of people in a group changed, with the deltas.",
                "tags": [
                    "group.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "group.members_synced"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `group.members_synced` here.",
                                        "enum": [
                                            "group.members_synced"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "group_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The group whose membership changed."
                                            },
                                            "team_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Team that owns the group."
                                            },
                                            "code": {
                                                "type": "string",
                                                "description": "Stable group code, immutable across renames."
                                            },
                                            "name": {
                                                "type": "string",
                                                "description": "Display name at the time of the sync."
                                            },
                                            "member_ids": {
                                                "type": "array",
                                                "description": "The membership **after** the sync: the complete list, not a page of it.",
                                                "items": {
                                                    "type": "string",
                                                    "format": "uuid"
                                                }
                                            },
                                            "added_ids": {
                                                "type": "array",
                                                "description": "Users who gained the group in this sync. Possibly empty.",
                                                "items": {
                                                    "type": "string",
                                                    "format": "uuid"
                                                }
                                            },
                                            "removed_ids": {
                                                "type": "array",
                                                "description": "Users who lost it. Possibly empty.",
                                                "items": {
                                                    "type": "string",
                                                    "format": "uuid"
                                                }
                                            },
                                            "member_count": {
                                                "type": "integer",
                                                "description": "`member_ids.length`, carried so a consumer can size the change without parsing the array."
                                            }
                                        },
                                        "required": [
                                            "group_id",
                                            "team_id",
                                            "code",
                                            "name",
                                            "member_ids",
                                            "added_ids",
                                            "removed_ids",
                                            "member_count"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "group.members_synced",
                                        "created_at": "2026-08-31T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "group_id": "1f68d92a-04c5-4e83-97b1-3d6a05e2f847",
                                            "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                            "code": "core-community",
                                            "name": "Core Community",
                                            "member_ids": [
                                                "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                                "6f9b2e37-c184-4a05-8d72-30e16bc9f458"
                                            ],
                                            "added_ids": [
                                                "6f9b2e37-c184-4a05-8d72-30e16bc9f458"
                                            ],
                                            "removed_ids": [
                                                "d05e1a83-7c46-4f29-b613-8ae407c9d251"
                                            ],
                                            "member_count": 2
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "group:view"
                ],
                "x-webhook-family": "group"
            }
        },
        "group.deleted": {
            "post": {
                "operationId": "webhook.group.deleted",
                "description": "### When this fires\n\nA group is deleted. Its permission and ability attachments are detached and its membership rows are removed; the people in it stay in the team but lose whatever the group granted. This is the final event you will receive for the given `group_id`.\n\n### Caveats\n\n- No per-collaborator event fires: the members' group rows cascade away with the group, and `group.members_synced` is emitted only by an explicit membership sync.\n- Members of the group are not removed from the team; only the group and the access it granted go away.\n\n### Related events\n\n- `group.created`: first event in the lifecycle.",
                "summary": "A group is deleted; its members lose the permissions it granted.",
                "tags": [
                    "group.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "group.deleted"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `group.deleted` here.",
                                        "enum": [
                                            "group.deleted"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "team_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Team that owned the group."
                                            },
                                            "group_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Group that was deleted."
                                            },
                                            "code": {
                                                "type": "string",
                                                "description": "Last-known stable group code."
                                            }
                                        },
                                        "required": [
                                            "team_id",
                                            "group_id",
                                            "code"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "group.deleted",
                                        "created_at": "2026-05-22T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "team_id": "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86",
                                            "group_id": "1f68d92a-04c5-4e83-97b1-3d6a05e2f847",
                                            "code": "core-community"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "group:view"
                ],
                "x-webhook-family": "group"
            }
        },
        "billing.invoice_created": {
            "post": {
                "operationId": "webhook.billing.invoice_created",
                "description": "### When this fires\n\nA new invoice is generated for the creator's Subscriby tier subscription. These events describe the creator's relationship with Subscriby itself, not their subscribers.\n\n### Caveats\n\n- This event is creator-side only. Subscriber invoices, if any, are not represented in `billing.*`.\n- Pairs with `billing.invoice_paid` on success and `billing.payment_failed` when the first attempt fails.\n\n### Related events\n\n- `billing.invoice_paid`: successful collection.\n- `billing.payment_failed`: failed collection attempt.",
                "summary": "A new invoice is generated for the creator's Subscriby tier.",
                "tags": [
                    "billing.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "billing.invoice_created"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `billing.invoice_created` here.",
                                        "enum": [
                                            "billing.invoice_created"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "creator_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Creator the invoice is addressed to. The only `data` key guaranteed present."
                                            },
                                            "invoice_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Provider invoice id. `null` if the provider payload carried no invoice id."
                                            },
                                            "amount": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "decimal",
                                                "description": "Invoice amount in major units of `currency`, formatted as a string. `null` if no amount was due."
                                            },
                                            "currency": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "ISO 4217 currency code. `null` if the provider payload carried no currency."
                                            },
                                            "hosted_invoice_url": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uri",
                                                "description": "URL to the provider-hosted invoice page. `null` on a draft invoice; Stripe issues it at finalization."
                                            },
                                            "attempt_count": {
                                                "type": [
                                                    "integer",
                                                    "null"
                                                ],
                                                "description": "Number of payment attempts so far. `0` at creation, `null` if the provider payload omitted it."
                                            }
                                        },
                                        "required": [
                                            "creator_id",
                                            "invoice_id",
                                            "amount",
                                            "currency",
                                            "hosted_invoice_url",
                                            "attempt_count"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "billing.invoice_created",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "creator_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "invoice_id": "in_1Nxy..",
                                            "amount": "49.00",
                                            "currency": "USD",
                                            "hosted_invoice_url": "https://invoice.stripe.com/..",
                                            "attempt_count": 0
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "billing:read"
                ],
                "x-webhook-family": "billing"
            }
        },
        "billing.invoice_paid": {
            "post": {
                "operationId": "webhook.billing.invoice_paid",
                "description": "### When this fires\n\nThe creator's tier invoice is paid in full and the account is marked current.\n\n### Caveats\n\n- Expect two deliveries per payment. Subscriby maps both Stripe `invoice.paid` and `invoice.payment_succeeded` onto this event. De-duplicate on `data.invoice_id`.\n- Recovery is not driven by this event. `past_due_since`, `locked_at` and the warning stamps are cleared when Stripe reports the subscription back at `active`/`trialing` on `customer.subscription.updated`, which emits no `billing.*` event of its own, so a consumer tracking lock state should treat this event as a hint, not the unlock signal.\n- A creator's lockdown never suspends their subscribers' billing (only new signups are blocked), so there is nothing to resume here.\n\n### Related events\n\n- `billing.invoice_created`: predecessor.\n- `billing.payment_failed`: alternative outcome.",
                "summary": "An invoice is paid in full.",
                "tags": [
                    "billing.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "billing.invoice_paid"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `billing.invoice_paid` here.",
                                        "enum": [
                                            "billing.invoice_paid"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "creator_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Creator the invoice was addressed to."
                                            },
                                            "invoice_id": {
                                                "type": "string",
                                                "description": "Provider invoice id."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "Paid amount in major units of `currency`."
                                            },
                                            "currency": {
                                                "type": "string",
                                                "description": "ISO 4217 currency code."
                                            },
                                            "hosted_invoice_url": {
                                                "type": "string",
                                                "format": "uri",
                                                "description": "URL to the provider-hosted invoice page (now showing paid status)."
                                            },
                                            "attempt_count": {
                                                "type": "integer",
                                                "description": "Provider-side attempt count on the invoice."
                                            }
                                        },
                                        "required": [
                                            "creator_id",
                                            "invoice_id",
                                            "amount",
                                            "currency",
                                            "hosted_invoice_url",
                                            "attempt_count"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "billing.invoice_paid",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "creator_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "invoice_id": "in_1Nxy..",
                                            "amount": "49.00",
                                            "currency": "USD",
                                            "hosted_invoice_url": "https://invoice.stripe.com/..",
                                            "attempt_count": 1
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "billing:read"
                ],
                "x-webhook-family": "billing"
            }
        },
        "billing.invoice_overdue": {
            "post": {
                "operationId": "webhook.billing.invoice_overdue",
                "description": "### When this fires\n\nThe creator's invoice is marked uncollectible by the payment provider. Coverage is partial: providers do not always send this signal for every overdue scenario.\n\n> **Deferred coverage.** Wired only to Stripe's `invoice.marked_uncollectible` signal. Stripe does not send that for every overdue scenario, so gaps are possible. Pair this event with `billing.payment_failed` and `billing.grace_period_warning` to cover overdue states reliably.\n\n### Caveats\n\n- Deferred in practice: coverage depends on Stripe sending `invoice.marked_uncollectible`. For full coverage of overdue states, listen for `billing.payment_failed` and `billing.grace_period_warning`.\n- The billing overdue policy drives lockdowns on its own daily cadence; see `billing.account_locked`.\n\n### Related events\n\n- `billing.payment_failed`: typical earlier signal.\n- `billing.grace_period_warning`, `billing.account_locked`: downstream signals.",
                "summary": "A creator invoice is marked overdue.",
                "tags": [
                    "billing.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "billing.invoice_overdue"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `billing.invoice_overdue` here.",
                                        "enum": [
                                            "billing.invoice_overdue"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "creator_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Creator the invoice was addressed to."
                                            },
                                            "invoice_id": {
                                                "type": "string",
                                                "description": "Provider invoice id."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "Invoice amount in major units of `currency`."
                                            },
                                            "currency": {
                                                "type": "string",
                                                "description": "ISO 4217 currency code."
                                            },
                                            "hosted_invoice_url": {
                                                "type": "string",
                                                "format": "uri",
                                                "description": "URL to the provider-hosted invoice page."
                                            },
                                            "attempt_count": {
                                                "type": "integer",
                                                "description": "Provider-side attempt count on the invoice."
                                            }
                                        },
                                        "required": [
                                            "creator_id",
                                            "invoice_id",
                                            "amount",
                                            "currency",
                                            "hosted_invoice_url",
                                            "attempt_count"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "billing.invoice_overdue",
                                        "created_at": "2026-04-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "creator_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "invoice_id": "in_1Nxy..",
                                            "amount": "49.00",
                                            "currency": "USD",
                                            "hosted_invoice_url": "https://invoice.stripe.com/..",
                                            "attempt_count": 3
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "billing:read"
                ],
                "x-webhook-family": "billing"
            }
        },
        "billing.payment_failed": {
            "post": {
                "operationId": "webhook.billing.payment_failed",
                "description": "### When this fires\n\nA scheduled charge against the creator's payment method fails. The platform will continue to retry inside the grace window.\n\n### Caveats\n\n- Multiple `billing.payment_failed` events can fire for the same `invoice_id` as Stripe retries.\n- Repeated failures escalate through the grace window; see `billing.grace_period_warning` and `billing.account_locked` for that progression.\n\n### Related events\n\n- `billing.invoice_paid`: successful resolution.\n- `billing.account_locked`: terminal state if recovery doesn't happen.",
                "summary": "A recurring charge against the creator's payment method fails.",
                "tags": [
                    "billing.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "billing.payment_failed"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `billing.payment_failed` here.",
                                        "enum": [
                                            "billing.payment_failed"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "creator_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Creator the invoice was addressed to."
                                            },
                                            "invoice_id": {
                                                "type": "string",
                                                "description": "Provider invoice id."
                                            },
                                            "amount": {
                                                "type": "string",
                                                "format": "decimal",
                                                "description": "Attempted amount in major units of `currency`."
                                            },
                                            "currency": {
                                                "type": "string",
                                                "description": "ISO 4217 currency code."
                                            },
                                            "hosted_invoice_url": {
                                                "type": "string",
                                                "format": "uri",
                                                "description": "URL to the provider-hosted invoice page."
                                            },
                                            "attempt_count": {
                                                "type": "integer",
                                                "description": "Provider-side retry count for this invoice."
                                            },
                                            "reason": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Stripe's `last_finalization_error.message`, falling back to `last_payment_error.message`. A human-readable sentence, not a decline code, and `null` when Stripe supplied neither. Do not pattern-match on it."
                                            }
                                        },
                                        "required": [
                                            "creator_id",
                                            "invoice_id",
                                            "amount",
                                            "currency",
                                            "hosted_invoice_url",
                                            "attempt_count",
                                            "reason"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "billing.payment_failed",
                                        "created_at": "2026-04-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "creator_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "invoice_id": "in_1Nxy..",
                                            "amount": "49.00",
                                            "currency": "USD",
                                            "hosted_invoice_url": "https://invoice.stripe.com/..",
                                            "attempt_count": 2,
                                            "reason": "Your card was declined."
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "billing:read"
                ],
                "x-webhook-family": "billing"
            }
        },
        "billing.trial_ending": {
            "post": {
                "operationId": "webhook.billing.trial_ending",
                "description": "### When this fires\n\nThe creator's own Subscriby trial crosses a reminder milestone on its way to converting. The trial collects a card at checkout and converts by itself, so this is the only advance notice a consumer gets before the first charge appears.\n\nMilestones are configured per deployment and fire largest-first. The default ladder is **72 hours** then **24 hours** before `trial_ends_at`, so a standard 7-day trial produces exactly two events. A milestone wider than the trial itself is skipped rather than fired at signup, so a trial shorter than 72 hours emits only the 24-hour event. Fires once per milestone, not once per trial; read `hours_remaining` to tell the two apart.\n\nSubscriby emails the creator alongside every emission, and mirrors it to their connected account when one is linked.\n\n### Reading `amount` correctly\n\nWhen `amount_estimated` is `false`, the figure comes from the upcoming Stripe invoice and already includes tax, any discount, and the transaction fees the creator's own sales metered during the trial. It is what will actually be taken.\n\nWhen `amount_estimated` is `true`, Stripe could not be reached and the figure is the plan's current price including any promotion in force. Treat it as indicative: do not reconcile against it, and do not surface it as a confirmed charge.\n\nA creator carrying a credit grant or account balance will legitimately see `\"0.00\"`; the trial still converts, the invoice is simply covered.\n\n### Caveats\n\n- **Not once per trial.** The default ladder emits twice. De-duplicate on `subscription_id` + `hours_remaining` if your consumer must act only once.\n- A trial the creator cancels before it converts stops emitting: no further milestones fire and no charge is raised.\n- The milestone ladder is deployment configuration, so do not hard-code `72` and `24`. Read `hours_remaining`.\n- `hours_remaining` is the milestone that fired, not the exact time left. The sweep runs hourly, so the true remaining time is somewhere within an hour below the value.\n\n### Related events\n\n- `billing.invoice_created`: the invoice this warning was about, once the trial actually converts.\n- `billing.payment_failed`: fires instead if the card on file is declined at conversion.\n- `subscription.trial_converting`: the subscriber-tier equivalent, for a creator's own members.",
                "summary": "The creator's platform trial is about to convert and take its first payment.",
                "tags": [
                    "billing.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "billing.trial_ending"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `billing.trial_ending` here.",
                                        "enum": [
                                            "billing.trial_ending"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "creator_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Creator whose trial is converting."
                                            },
                                            "plan_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "Platform plan the trial converts onto. `null` if the tier could not be resolved."
                                            },
                                            "subscription_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "The creator's platform subscription row."
                                            },
                                            "trial_ends_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the trial converts and the charge is raised."
                                            },
                                            "hours_remaining": {
                                                "type": "integer",
                                                "description": "Which milestone fired: `72` or `24` on the default ladder. Not the live countdown."
                                            },
                                            "amount": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "decimal",
                                                "description": "Total that will be charged, e.g. `\"19.00\"`. `null` only when no currency could be resolved."
                                            },
                                            "currency": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "description": "Uppercase ISO 4217 code for `amount`."
                                            },
                                            "amount_estimated": {
                                                "type": "boolean",
                                                "description": "`true` when `amount` is the plan's current price including any promotion in force because the upcoming invoice was unreachable."
                                            }
                                        },
                                        "required": [
                                            "creator_id",
                                            "plan_id",
                                            "subscription_id",
                                            "trial_ends_at",
                                            "hours_remaining",
                                            "amount",
                                            "currency",
                                            "amount_estimated"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "billing.trial_ending",
                                        "created_at": "2026-08-23T09:00:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "creator_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
                                            "subscription_id": "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4",
                                            "trial_ends_at": "2026-08-26T09:00:00Z",
                                            "hours_remaining": 72,
                                            "amount": "19.00",
                                            "currency": "USD",
                                            "amount_estimated": false
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "billing:read"
                ],
                "x-webhook-family": "billing"
            }
        },
        "billing.grace_period_warning": {
            "post": {
                "operationId": "webhook.billing.grace_period_warning",
                "description": "### When this fires\n\nThe creator's account reaches the warning milestone on its overdue clock. That milestone depends on the plan's base price: **day 3** for a creator on a zero-base-price (Free) plan, whose lockdown lands on day 7, and **day 23** for a paid plan, whose lockdown lands on day 30. Fires once per past-due cycle.\n\nRead `days_until_lockdown` from the payload rather than assuming a fixed offset; it carries the actual remaining days for that creator's tier.\n\n### Caveats\n\n- Each past-due cycle produces at most one `billing.grace_period_warning`. If the account recovers and re-enters past_due later, a new cycle and a new warning may issue.\n- After lockdown the clock keeps running: a deletion warning at 53 days locked and account deletion at 60 days locked on paid/trial thresholds (3 and 7 days on Free). Neither stage emits a `billing.*` webhook; they surface as notifications only.\n\n### Related events\n\n- `billing.payment_failed`: the chain of failed collections leading here.\n- `billing.account_locked`: fires when the lockdown day arrives: 7 days after this event on a paid tier, 4 on Free or an unconverted trial.",
                "summary": "The creator is approaching automatic lockdown for an unpaid invoice.",
                "tags": [
                    "billing.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "billing.grace_period_warning"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `billing.grace_period_warning` here.",
                                        "enum": [
                                            "billing.grace_period_warning"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "creator_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Creator approaching lockdown."
                                            },
                                            "past_due_since": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the past-due state began."
                                            },
                                            "days_until_lockdown": {
                                                "type": "integer",
                                                "description": "Whole days from emission until lockdown for this creator's tier. Typically `7` on a paid tier and `4` on Free or an unconverted trial; lower if the daily sweep is late, and `0` at the floor."
                                            }
                                        },
                                        "required": [
                                            "creator_id",
                                            "past_due_since",
                                            "days_until_lockdown"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "billing.grace_period_warning",
                                        "created_at": "2026-05-11T08:00:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "creator_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "past_due_since": "2026-04-18T00:00:00Z",
                                            "days_until_lockdown": 7
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "billing:read"
                ],
                "x-webhook-family": "billing"
            }
        },
        "billing.account_locked": {
            "post": {
                "operationId": "webhook.billing.account_locked",
                "description": "### When this fires\n\nThe creator's account reaches its tier's past-due lockdown: day 30 on a paid tier, day 7 on Free or an unconverted trial. New signups on the project's portal pages are blocked and the dashboard surfaces a lockdown banner.\n\n### Caveats\n\n- Lockdown is reversible: a successful payment fires `billing.invoice_paid` and the lockdown is cleared automatically. There is no dedicated \"account_unlocked\" event.\n- Existing subscribers retain access to project resources during lockdown; only new signups are blocked.\n\n### Related events\n\n- `billing.grace_period_warning`: the warning that precedes it, 7 days earlier on a paid tier and 4 on Free or an unconverted trial.\n- `billing.invoice_paid`: automatic unlock signal.",
                "summary": "The account hits its past-due lockdown.",
                "tags": [
                    "billing.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "billing.account_locked"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `billing.account_locked` here.",
                                        "enum": [
                                            "billing.account_locked"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "creator_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Creator that was locked."
                                            },
                                            "past_due_since": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the past-due state began."
                                            },
                                            "locked_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "When the lockdown took effect."
                                            }
                                        },
                                        "required": [
                                            "creator_id",
                                            "past_due_since",
                                            "locked_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "billing.account_locked",
                                        "created_at": "2026-05-18T00:00:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "creator_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "past_due_since": "2026-04-18T00:00:00Z",
                                            "locked_at": "2026-05-18T00:00:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "billing:read"
                ],
                "x-webhook-family": "billing"
            }
        },
        "billing.tier_upgraded": {
            "post": {
                "operationId": "webhook.billing.tier_upgraded",
                "description": "### When this fires\n\nThe creator switches their Subscriby subscription to a higher-priced tier. Pro-ration is applied through the payment provider, except when the creator is still inside their platform trial, where the switch is not prorated because nothing has been paid yet.\n\n### Caveats\n\n- Tier changes can unlock features (e.g. Teams on Growth+); event consumers should refresh tier caches on receipt.\n- Pro-ration charges fire `billing.invoice_created` separately for the proration line (not on an upgrade taken during the platform trial).\n\n### Related events\n\n- `billing.tier_downgraded`: opposite direction.\n- `billing.invoice_created`: proration invoice.",
                "summary": "The creator upgrades to a higher Subscriby tier.",
                "tags": [
                    "billing.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "billing.tier_upgraded"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `billing.tier_upgraded` here.",
                                        "enum": [
                                            "billing.tier_upgraded"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "creator_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Creator whose tier changed."
                                            },
                                            "from_tier": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Previous tier **plan id**. Always present: a first subscription goes through checkout and emits no tier event."
                                            },
                                            "to_tier": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "New tier **plan id**."
                                            },
                                            "effective_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Always the emission time: upgrades take effect immediately."
                                            }
                                        },
                                        "required": [
                                            "creator_id",
                                            "from_tier",
                                            "to_tier",
                                            "effective_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "billing.tier_upgraded",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "creator_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "from_tier": "308eb3da-1eb6-11f0-b4f2-d8bbc173f8c3",
                                            "to_tier": "882b72bb-1eb6-11f0-b4f2-d8bbc173f8c3",
                                            "effective_at": "2026-05-18T10:05:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "billing:read"
                ],
                "x-webhook-family": "billing"
            }
        },
        "billing.tier_downgraded": {
            "post": {
                "operationId": "webhook.billing.tier_downgraded",
                "description": "### When this fires\n\nThe creator switches their Subscriby subscription to a lower tier. The change lands at the end of the period they have already paid for, not at `effective_at`: the current phase runs to its existing end date and the lower tier begins after it.\n\n### Caveats\n\n- `effective_at` is stamped at emission time and is never in the future, even when the provider defers the billing change to the next renewal boundary. Do not use it to schedule feature revocation.\n- Tier-locked features (Teams, custom roles, etc.) may become read-only or hidden once the current paid period ends, never at `effective_at`.\n\n### Related events\n\n- `billing.tier_upgraded`: opposite direction.\n- `billing.tier_cancelled`: terminal downgrade path.",
                "summary": "The creator downgrades to a lower Subscriby tier.",
                "tags": [
                    "billing.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "billing.tier_downgraded"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `billing.tier_downgraded` here.",
                                        "enum": [
                                            "billing.tier_downgraded"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "creator_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Creator whose tier changed."
                                            },
                                            "from_tier": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Previous tier **plan id**. Always present: a first subscription emits no tier event."
                                            },
                                            "to_tier": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "New tier **plan id**."
                                            },
                                            "effective_at": {
                                                "type": "string",
                                                "format": "date-time",
                                                "description": "Always the emission time, **never** a future date."
                                            }
                                        },
                                        "required": [
                                            "creator_id",
                                            "from_tier",
                                            "to_tier",
                                            "effective_at"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload": {
                                    "summary": "Delivery",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "billing.tier_downgraded",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "creator_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "from_tier": "882b72bb-1eb6-11f0-b4f2-d8bbc173f8c3",
                                            "to_tier": "308eb3da-1eb6-11f0-b4f2-d8bbc173f8c3",
                                            "effective_at": "2026-05-18T10:05:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "billing:read"
                ],
                "x-webhook-family": "billing"
            }
        },
        "billing.tier_cancelled": {
            "post": {
                "operationId": "webhook.billing.tier_cancelled",
                "description": "### When this fires\n\nThe creator cancels their Subscriby tier subscription. The account remains usable until the current period ends.\n\nThis event has **two distinct payload shapes** depending on which side initiated the cancellation. Branch on the presence of `effective_at` versus `subscription_id`.\n\n### Caveats\n\n- **Expect this event twice for a single cancellation.** The dashboard shape fires when the creator cancels; the provider shape fires later, when the period actually ends and the provider deletes the subscription. De-duplicate on `data.creator_id` if you only want to act once.\n- Cancellation does not refund the active period; there is a no-refunds policy on creator tier billing.\n- The account does not auto-lock at `effective_at` unless past_due conditions also apply; it gracefully drops to the Free tier feature set.\n\n### Related events\n\n- `billing.tier_downgraded`: alternative path that retains paid features.\n- `billing.invoice_paid`: last paid invoice before cancellation.",
                "summary": "The creator cancels their Subscriby subscription.",
                "tags": [
                    "billing.* events"
                ],
                "parameters": [
                    {
                        "name": "SB-Signature",
                        "in": "header",
                        "required": true,
                        "description": "`t=<unix seconds>,v1=<hex>`: the HMAC-SHA256 of `\"<t>.<raw body>\"` under the endpoint's secret. Verify it before acting, and refuse a `t` more than 300 seconds from now. During a secret rotation a `v0=` signature under the previous secret may precede `v1=`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1758636300,v1=5f1c…"
                    },
                    {
                        "name": "SB-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's ULID, bare. The envelope's `id` is the same ULID prefixed `evt_`, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "01HXDELIVERY000000000TST"
                    },
                    {
                        "name": "SB-Event-Name",
                        "in": "header",
                        "required": true,
                        "description": "The event name, the same as the envelope's `type`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "billing.tier_cancelled"
                    },
                    {
                        "name": "Content-Type",
                        "in": "header",
                        "required": true,
                        "description": "Always `application/json`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "application/json"
                    },
                    {
                        "name": "User-Agent",
                        "in": "header",
                        "required": true,
                        "description": "Always `Subscriby-Webhooks/1.0`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Subscriby-Webhooks/1.0"
                    }
                ],
                "requestBody": {
                    "description": "The signed JSON envelope posted to your endpoint.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The envelope every event is delivered in.",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "A ULID unique to the event, prefixed `evt_`. Every retry carries the same id, so it is the key to deduplicate on."
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "The event name, always `billing.tier_cancelled` here.",
                                        "enum": [
                                            "billing.tier_cancelled"
                                        ]
                                    },
                                    "created_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event was emitted, server time, ISO 8601."
                                    },
                                    "api_version": {
                                        "type": "string",
                                        "description": "The contract version of the payload shape, `2026-05-01` today. A breaking change to a shape ships under a new version."
                                    },
                                    "project_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "uuid",
                                        "description": "The project the event belongs to; null for team-scoped and billing events."
                                    },
                                    "data": {
                                        "type": "object",
                                        "description": "The event-specific payload. Keys that do not apply to a given emission are omitted rather than sent as null, so check for presence.",
                                        "properties": {
                                            "creator_id": {
                                                "type": "string",
                                                "format": "uuid",
                                                "description": "Creator whose tier was cancelled. Present on both shapes."
                                            },
                                            "plan_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "uuid",
                                                "description": "Tier **plan id**. Present on both shapes."
                                            },
                                            "effective_at": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "date-time",
                                                "description": "Dashboard shape only. When the cancellation takes effect, i.e. end of paid period."
                                            },
                                            "subscription_id": {
                                                "type": "string",
                                                "description": "Provider shape only. The provider-side subscription id."
                                            },
                                            "status": {
                                                "type": "string",
                                                "description": "Provider shape only. Provider subscription status, e.g. `canceled`."
                                            },
                                            "canceled_at": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "date-time",
                                                "description": "Provider shape only. When the provider recorded the cancellation."
                                            }
                                        },
                                        "required": [
                                            "creator_id",
                                            "plan_id"
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "type",
                                    "created_at",
                                    "api_version",
                                    "project_id",
                                    "data"
                                ]
                            },
                            "examples": {
                                "payload-creator-cancels-in-the-dashboard": {
                                    "summary": "creator cancels in the dashboard",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "billing.tier_cancelled",
                                        "created_at": "2026-05-18T10:05:00Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "creator_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "plan_id": "882b72bb-1eb6-11f0-b4f2-d8bbc173f8c3",
                                            "effective_at": "2026-06-18T00:00:00Z"
                                        }
                                    }
                                },
                                "payload-provider-reports-the-subscription-deleted": {
                                    "summary": "provider reports the subscription deleted",
                                    "value": {
                                        "id": "evt_01HX...",
                                        "type": "billing.tier_cancelled",
                                        "created_at": "2026-06-18T00:00:05Z",
                                        "api_version": "2026-05-01",
                                        "project_id": null,
                                        "data": {
                                            "creator_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80",
                                            "subscription_id": "sub_1PabcdEFGH",
                                            "plan_id": "882b72bb-1eb6-11f0-b4f2-d8bbc173f8c3",
                                            "status": "canceled",
                                            "canceled_at": "2026-06-18T00:00:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "2XX": {
                        "description": "Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored."
                    },
                    "default": {
                        "description": "Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or `POST /v1/webhook-deliveries/{delivery}/retry`. After 20 consecutive failures the endpoint is paused until it is resumed."
                    }
                },
                "x-required-scopes": [
                    "billing:read"
                ],
                "x-webhook-family": "billing"
            }
        }
    },
    "components": {
        "securitySchemes": {
            "bearerToken": {
                "type": "http",
                "description": "A personal access token minted on the dashboard under Settings, then Tokens, sent as `Authorization: Bearer sbt_live_…`. The token carries the abilities each endpoint lists under **Requires ability** and is frozen to one team.",
                "scheme": "bearer",
                "bearerFormat": "sbt_<env>_<id>_<secret>"
            }
        },
        "schemas": {
            "AccessCodeExpiryPreset": {
                "type": "string",
                "description": "When a generated access code stops being redeemable. The presets cover what creators pick nearly every time; `Custom` takes an amount and a unit for the rest. The instant is resolved when the batch is generated, so every code in a batch shares one expiry.\n| |\n|---|\n| `no_expiry` <br/> The code stays redeemable until it is used or revoked. |\n| `1_day` <br/>  |\n| `1_week` <br/>  |\n| `1_month` <br/>  |\n| `1_year` <br/>  |\n| `custom` <br/> An amount of a unit, supplied alongside the preset. |",
                "enum": [
                    "no_expiry",
                    "1_day",
                    "1_week",
                    "1_month",
                    "1_year",
                    "custom"
                ],
                "title": "AccessCodeExpiryPreset"
            },
            "AccessCodeExpiryUnit": {
                "type": "string",
                "description": "The unit of a custom access-code expiry. Deliberately no minutes or hours: a code that dies within the hour it was generated is a support ticket, not a feature.\n",
                "enum": [
                    "days",
                    "weeks",
                    "months",
                    "years"
                ],
                "title": "AccessCodeExpiryUnit"
            },
            "AccessCodeExportType": {
                "type": "string",
                "description": "How a generated batch of access codes is handed to the creator. Both routes go through the creator's chat with the platform bot, because the batch is generated on a queue after the request returned and the bot is the one channel every creator already has open.\n| |\n|---|\n| `file` <br/> One CSV with every code, for spreadsheets and automation. |\n| `messages` <br/> One forwardable message per code, capped so a batch cannot flood the chat. |",
                "enum": [
                    "file",
                    "messages"
                ],
                "title": "AccessCodeExportType"
            },
            "AccessCodeResource": {
                "type": "object",
                "description": "One access code: a pending subscription row a subscriber can redeem, with the code itself masked.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The code's id, the value the revoke endpoint takes.",
                        "examples": [
                            "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                        ]
                    },
                    "plan_id": {
                        "type": "string",
                        "description": "The plan the code activates.",
                        "examples": [
                            "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b"
                        ]
                    },
                    "subscriber_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The member who redeemed the code; null while it is unredeemed.",
                        "examples": [
                            null
                        ]
                    },
                    "code_masked": {
                        "description": "The code with every character but the last five replaced by `*`. The plaintext ships only through the dashboard export or the messages the batch was delivered as.",
                        "anyOf": [
                            {
                                "type": "string",
                                "examples": [
                                    "******12345"
                                ]
                            },
                            {
                                "type": "string",
                                "enum": [
                                    ""
                                ],
                                "examples": [
                                    "******12345"
                                ]
                            }
                        ]
                    },
                    "expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When an unredeemed code stops working, ISO 8601; null for a code that never expires.",
                        "examples": [
                            "2026-08-01T00:00:00Z"
                        ]
                    },
                    "redeemed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a subscriber claimed the code, ISO 8601; null while it is unredeemed.",
                        "examples": [
                            null
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the batch was generated, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "plan_id",
                    "subscriber_id",
                    "code_masked",
                    "expires_at",
                    "redeemed_at",
                    "created_at"
                ],
                "title": "AccessCodeResource"
            },
            "AccessGrantResource": {
                "type": "object",
                "description": "An access grant: the ledger's record that a purchase admits its holder to one resource, and per dated window for a pass, saying which connector gave the access, how, where it stands and, when it failed, why.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The grant's id.",
                        "examples": [
                            "7d1c3e9a-2b64-4f0e-9a58-3c6b1d8e2f47"
                        ]
                    },
                    "subscription_id": {
                        "type": "string",
                        "description": "The purchase the grant belongs to.",
                        "examples": [
                            "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                        ]
                    },
                    "resource_id": {
                        "type": "string",
                        "description": "The resource the grant admits the holder to.",
                        "examples": [
                            "c9e21f37-8a4b-4d56-b1e0-2f7c9d3a6e15"
                        ]
                    },
                    "window_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The dated pass window the grant is for; null for continuous access.",
                        "examples": [
                            null
                        ]
                    },
                    "identity_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The connector account admitted, the same id the member's identities endpoint returns; null while none is linked or for a hand-arranged perk.",
                        "examples": [
                            "0c2d8a7e-4b1f-4d3e-9a6b-2f5e8c1d7a90"
                        ]
                    },
                    "connector": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The connector that gave the access, by key; null for a manual perk.",
                        "examples": [
                            "telegram"
                        ]
                    },
                    "mode": {
                        "type": "string",
                        "description": "How the access is given: `bearer_link` (a personal invite link the member comes through), `membership` (the connector added the member itself), `role` (a role was assigned) or `creator_task` (the creator has to do something by hand).",
                        "enum": [
                            "bearer_link",
                            "membership",
                            "role",
                            "creator_task"
                        ],
                        "examples": [
                            "bearer_link"
                        ]
                    },
                    "state": {
                        "type": "string",
                        "description": "`pending_identity` (the member has not linked an account on that connector yet; issued the moment they connect one), `pending` (issued, not yet used), `held` (issued ahead of a pass window and released when it opens), `granted`, `revoked` or `failed`.",
                        "enum": [
                            "pending_identity",
                            "pending",
                            "held",
                            "granted",
                            "revoked",
                            "failed"
                        ],
                        "examples": [
                            "granted"
                        ]
                    },
                    "reference": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The connector's handle on the grant (the invite link on a connector that grants by link); null before anything was issued. Treat it as a secret: whoever holds a bearer link can use it.",
                        "examples": [
                            "https://t.me/+AbCdEfGhIjKlMnOp"
                        ]
                    },
                    "granted_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the access was granted, ISO 8601; null until then.",
                        "examples": [
                            "2026-09-12T10:05:00Z"
                        ]
                    },
                    "revoked_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the access was revoked, ISO 8601; null while standing.",
                        "examples": [
                            null
                        ]
                    },
                    "failure_kind": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why a `failed` grant failed: `unreachable`, `not_permitted`, `target_missing`, `rate_limited`, `configuration`, `transient` or `other`; null otherwise.",
                        "enum": [
                            "unreachable",
                            "not_permitted",
                            "target_missing",
                            "rate_limited",
                            "configuration",
                            "transient",
                            "other",
                            null
                        ],
                        "examples": [
                            null
                        ]
                    },
                    "failure_detail": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The sentence the creator sees in the dashboard for a failed grant; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the ledger row was written, ISO 8601.",
                        "examples": [
                            "2026-09-12T10:04:58Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "subscription_id",
                    "resource_id",
                    "window_id",
                    "identity_id",
                    "connector",
                    "mode",
                    "state",
                    "reference",
                    "granted_at",
                    "revoked_at",
                    "failure_kind",
                    "failure_detail",
                    "created_at"
                ],
                "title": "AccessGrantResource"
            },
            "AccountExportResource": {
                "type": "object",
                "description": "One export of the caller's account: its state, when it was asked for and finished, how long its archive lives, and a signed link to download it while it is ready.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The export's id.",
                        "examples": [
                            "4f2a7c1e-9b3d-4e8a-a6c5-1d2e3f4a5b6c"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "`queued`, `building`, `ready`, `failed` or `expired`. Only `ready` carries a `download_url`.",
                        "enum": [
                            "queued",
                            "building",
                            "ready",
                            "failed",
                            "expired"
                        ],
                        "examples": [
                            "ready"
                        ]
                    },
                    "reason": {
                        "type": "string",
                        "description": "`manual` for a request from Settings or the API, `deletion` for the archive a scheduled account deletion builds.",
                        "enum": [
                            "manual",
                            "deletion"
                        ],
                        "examples": [
                            "manual"
                        ]
                    },
                    "requested_at": {
                        "type": "string",
                        "description": "When the export was asked for, ISO 8601.",
                        "examples": [
                            "2026-10-07T09:12:00Z"
                        ]
                    },
                    "completed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the build finished, ISO 8601, or null while it runs.",
                        "examples": [
                            "2026-10-07T09:14:21Z"
                        ]
                    },
                    "expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the archive is removed, ISO 8601, or null before it exists.",
                        "examples": [
                            "2026-10-14T09:14:21Z"
                        ]
                    },
                    "size_bytes": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The archive's size, or null before it exists.",
                        "examples": [
                            184320
                        ]
                    },
                    "projects_count": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "How many projects the archive holds, or null before it exists.",
                        "examples": [
                            2
                        ]
                    },
                    "download_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A signed link to the zip, present only while `status` is `ready`; it stops working at `download_url_expires_at`, and reading the export again mints a fresh one.",
                        "examples": [
                            "https://app.subscriby.net/account/exports/4f2a7c1e-9b3d-4e8a-a6c5-1d2e3f4a5b6c/download?expires=1760000000&signature=0f3c…"
                        ]
                    },
                    "download_url_expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When `download_url` stops working, ISO 8601, or null without a link.",
                        "examples": [
                            "2026-10-08T09:30:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "status",
                    "reason",
                    "requested_at",
                    "completed_at",
                    "expires_at",
                    "size_bytes",
                    "projects_count",
                    "download_url",
                    "download_url_expires_at"
                ],
                "title": "AccountExportResource"
            },
            "ActivityResource": {
                "type": "object",
                "description": "One activity-log entry: what changed on a subject, who caused it and through which surface.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The entry's id.",
                        "examples": [
                            "92e4c1b6-70da-4f38-8517-b036ae94d7c2"
                        ]
                    },
                    "log_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The log the entry was written to; `default` for every application entry.",
                        "examples": [
                            "default"
                        ]
                    },
                    "description": {
                        "type": "string",
                        "description": "What happened, in the recorder's words, such as `created` or `updated`.",
                        "examples": [
                            "updated"
                        ]
                    },
                    "event": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The lifecycle event the entry records: `created`, `updated`, `deleted` or `restored`; null for a manual entry.",
                        "examples": [
                            "updated"
                        ]
                    },
                    "subject_type": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The kind of thing that changed, as a short alias such as `project`, `project-subscription`, `project-subscription-plan`, `project-user` or `project-resource`. Treat it as an opaque string.",
                        "examples": [
                            "project"
                        ]
                    },
                    "subject_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The id of the thing that changed.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "causer_type": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The kind of actor, as a short alias such as `user`; null for a system change.",
                        "examples": [
                            "user"
                        ]
                    },
                    "causer_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The actor's id; null for a system change.",
                        "examples": [
                            "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                        ]
                    },
                    "actor_kind": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The surface the change came through: `human` (dashboard), `api_token` (REST), `mcp` (an MCP tool), `zapier`, `webhook` or `system` (a scheduled job). Filter on it client-side to separate what an agent did from dashboard clicks.",
                        "examples": [
                            "api_token"
                        ]
                    },
                    "properties": {
                        "type": "object",
                        "description": "What was recorded with the change, typically `attributes` (the new values) and `old` (the previous ones). Keys matching `token`, `secret`, `password`, `api_key` or `api_secret`, at any depth and in any case, are stripped before the response leaves the server.",
                        "additionalProperties": {}
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the change was recorded, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "log_name",
                    "description",
                    "event",
                    "subject_type",
                    "subject_id",
                    "causer_type",
                    "causer_id",
                    "actor_kind",
                    "properties",
                    "created_at"
                ],
                "title": "ActivityResource"
            },
            "ActivitySubjectType": {
                "type": "string",
                "description": "The subjects the public activity surfaces may be asked about. The alias is the contract, not the class name: the REST endpoint used to accept any model FQCN as a fallback, which let a caller probe for class names and pointed a user-controlled string at `::query()`. Only these aliases resolve now, and each names the one model it stands for.  Two vocabularies are accepted because two surfaces documented them. The REST endpoint has always said `member`, `subscription` and `plan`; the MCP tool has always said `project-user`, `project-subscription` and `project-subscription-plan`. Both map to the same model, so an agent written against either keeps working.\n| |\n|---|\n| `project` <br/>  |\n| `subscription` <br/>  |\n| `project-subscription` <br/> The MCP spelling of a subscription. |\n| `member` <br/>  |\n| `project-user` <br/> The MCP spelling of a member. |\n| `plan` <br/>  |\n| `project-subscription-plan` <br/> The MCP spelling of a plan. |\n| `access-code` <br/> An access code is a pending subscription row, so its history lives under the subscription model. |\n| `coupon` <br/>  |\n| `project-resource` <br/>  |\n| `referral-program` <br/>  |\n| `referral-affiliate` <br/>  |\n| `smart-link` <br/>  |\n| `sequence` <br/>  |\n| `knowledge-entry` <br/>  |",
                "enum": [
                    "project",
                    "subscription",
                    "project-subscription",
                    "member",
                    "project-user",
                    "plan",
                    "project-subscription-plan",
                    "access-code",
                    "coupon",
                    "project-resource",
                    "referral-program",
                    "referral-affiliate",
                    "smart-link",
                    "sequence",
                    "knowledge-entry"
                ],
                "title": "ActivitySubjectType"
            },
            "AlertClass": {
                "type": "string",
                "description": "The families a creator's notifications fall into, for routing. A creator picks where each class goes; the router reads their alert destinations by class. The critical classes always also go out by email, whatever the creator picked, because they are the ones that arrive when the connector the creator would otherwise read them on has just failed.\n",
                "enum": [
                    "sales",
                    "support",
                    "recovery",
                    "billing",
                    "security",
                    "passes",
                    "onboarding",
                    "partner",
                    "retention",
                    "copilot"
                ],
                "title": "AlertClass"
            },
            "AlertDestinationKind": {
                "type": "string",
                "description": "What kind of place a creator's alert can be sent to. A connector identity is reached through that connector's messenger, an email through mail, and a push device through the mobile apps once they exist; the kind decides which channel the router picks, and adding a kind is a case here and a row per creator, never a schema change.\n",
                "enum": [
                    "connector_identity",
                    "email",
                    "push_device"
                ],
                "title": "AlertDestinationKind"
            },
            "AlertDestinationResource": {
                "type": "object",
                "description": "One place the caller's creator alerts go: a connected account or an email address, with the classes of alert routed to it.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The destination's id.",
                        "examples": [
                            "5d3a9c1e-7f2b-4e8d-a1c6-9b0f3e2d4a71"
                        ]
                    },
                    "kind": {
                        "type": "string",
                        "description": "`connector_identity` for a connected account, `email` for an address. `push_device` is reserved for the creator apps.",
                        "enum": [
                            "connector_identity",
                            "email",
                            "push_device"
                        ],
                        "examples": [
                            "connector_identity"
                        ]
                    },
                    "target": {
                        "type": "string",
                        "description": "The connected account's id (the same value `GET /v1/me/identities` returns behind a linked identity) for `connector_identity`, or the email address for `email`.",
                        "examples": [
                            "0c2d8a7e-4b1f-4d3e-9a6b-2f5e8c1d7a90"
                        ]
                    },
                    "classes": {
                        "type": [
                            "array",
                            "null"
                        ],
                        "description": "The alert classes routed here: any of `sales`, `support`, `recovery`, `billing`, `security`, `passes`, `onboarding`. `null` means every class; `[]` keeps the destination but sends it nothing.",
                        "items": {
                            "examples": [
                                "sales"
                            ]
                        }
                    },
                    "is_primary": {
                        "type": "boolean",
                        "description": "Whether this is the destination of your primary connected account. Derived from your linked identities, never set through the API.",
                        "examples": [
                            true
                        ]
                    },
                    "verified_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the destination was confirmed reachable, ISO 8601; null while unverified.",
                        "examples": [
                            "2026-09-12T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "kind",
                    "target",
                    "classes",
                    "is_primary",
                    "verified_at"
                ],
                "title": "AlertDestinationResource"
            },
            "ApiError": {
                "type": "object",
                "properties": {
                    "error": {
                        "type": "object",
                        "description": "The one envelope every failure uses.",
                        "properties": {
                            "code": {
                                "type": "string",
                                "description": "The stable identifier to branch on. `message` may be reworded between releases; a code never changes meaning.",
                                "enum": [
                                    "VALIDATION_FAILED",
                                    "AUTHENTICATION_REQUIRED",
                                    "TOKEN_MISSING_ABILITY",
                                    "TENANT_MISMATCH",
                                    "RESOURCE_NOT_FOUND",
                                    "PLAN_CURRENCY_MISMATCH",
                                    "PLAN_PROVIDER_UNSUPPORTED",
                                    "PAYMENT_METHOD_NOT_CONFIGURED",
                                    "SUBSCRIPTION_ALREADY_ACTIVE",
                                    "ACCESS_CODE_INVALID",
                                    "ACCESS_CODE_EXPIRED",
                                    "ACCESS_CODE_ALREADY_REDEEMED",
                                    "ACCESS_CODE_CAP_EXCEEDED",
                                    "IDEMPOTENCY_KEY_MISSING",
                                    "IDEMPOTENCY_KEY_REUSED",
                                    "IDEMPOTENCY_REPLAY_IN_PROGRESS",
                                    "METHOD_NOT_ALLOWED",
                                    "RATE_LIMITED",
                                    "TEAM_TIER_REQUIRED",
                                    "CONNECTOR_UNAVAILABLE",
                                    "CONNECTOR_TIER_REQUIRED",
                                    "CONNECTOR_NOT_INSTALLED",
                                    "CONNECTOR_NOT_CONNECTED",
                                    "IDENTITY_NOT_LINKED",
                                    "WEBHOOK_ENDPOINT_UNREACHABLE",
                                    "FORBIDDEN",
                                    "INTERNAL_SERVER_ERROR"
                                ]
                            },
                            "message": {
                                "type": "string",
                                "description": "A human-readable summary of what went wrong."
                            },
                            "docs_url": {
                                "type": "string",
                                "format": "uri",
                                "description": "The anchor for this code on the error reference."
                            },
                            "remediation": {
                                "type": "string",
                                "description": "One sentence on what the caller should do about it."
                            },
                            "request_id": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The trace identifier to quote to support."
                            },
                            "fields": {
                                "type": "object",
                                "description": "Only on `VALIDATION_FAILED`: each offending key mapped to the messages of the rules it broke.",
                                "additionalProperties": {
                                    "type": "array",
                                    "items": {
                                        "type": "string"
                                    }
                                }
                            },
                            "context": {
                                "type": "object",
                                "description": "Only when the failure has more to say, such as `required_ability` on `TOKEN_MISSING_ABILITY` or `reason` on a refused connector call.",
                                "additionalProperties": {}
                            }
                        },
                        "required": [
                            "code",
                            "message",
                            "docs_url",
                            "remediation",
                            "request_id"
                        ]
                    }
                },
                "required": [
                    "error"
                ],
                "title": "ApiError"
            },
            "BroadcastAudience": {
                "type": "string",
                "description": "Who a broadcast is addressed to. Previously a bare string that BroadcastMessageJob fed to `ProjectUserStatus::tryFrom()`, which quietly meant \"anything unrecognised  * broadcasts to everyone\" — a typo in the audience widened the send rather than refusing it. The pass segments cannot be expressed as a status at all: they are a fact about a subscription bound to a window, not about the member.  Declaration order is the order the picker offers them, so each pass segment's every-window form sits above the one that asks for a single date.  The backing values of the status-derived cases match ProjectUserStatus so a broadcast queued before this enum existed still resolves.\n",
                "enum": [
                    "all",
                    "customer",
                    "trialing",
                    "lead",
                    "churned",
                    "expiring_soon",
                    "cancelled_still_active",
                    "paused",
                    "trialing_cardless",
                    "all_pass_holders",
                    "all_pass_holders_not_in_queue",
                    "pass_holders",
                    "pass_holders_not_in_queue"
                ],
                "title": "BroadcastAudience"
            },
            "BulkGenerateAccessCodesRequest": {
                "type": "object",
                "description": "A batch of access codes to generate: how many, how they are delivered to you, and when they expire.",
                "properties": {
                    "quantity": {
                        "type": "integer",
                        "description": "How many codes to generate, 1 to 1,000 per batch.",
                        "minimum": 1,
                        "maximum": 1000
                    },
                    "export_type": {
                        "description": "How the plaintext codes reach you: `file` for one downloadable file, `messages` for one message per code to your connected account. There is no silent mode; to read the codes programmatically, list them once the batch has finished.\n| |\n|---|\n| `file` <br/> One CSV with every code, for spreadsheets and automation. |\n| `messages` <br/> One forwardable message per code, capped so a batch cannot flood the chat. |",
                        "$ref": "#/components/schemas/AccessCodeExportType"
                    },
                    "consent": {
                        "description": "Must be `true` when `export_type` is `messages`: one message per code is high volume and can trip the connector's rate limits, so you acknowledge it explicitly. Ignored otherwise.",
                        "enum": [
                            "yes",
                            "on",
                            "1",
                            1,
                            "true",
                            true
                        ]
                    },
                    "expiry_preset": {
                        "description": "When unredeemed codes stop working: `no_expiry`, `1_day`, `1_week`, `1_month`, `1_year`, or `custom` with an amount and a unit.\n| |\n|---|\n| `no_expiry` <br/> The code stays redeemable until it is used or revoked. |\n| `1_day` <br/>  |\n| `1_week` <br/>  |\n| `1_month` <br/>  |\n| `1_year` <br/>  |\n| `custom` <br/> An amount of a unit, supplied alongside the preset. |",
                        "$ref": "#/components/schemas/AccessCodeExpiryPreset"
                    },
                    "custom_expiry_amount": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "How many units the codes live for; required when `expiry_preset` is `custom`, at least 1.",
                        "minimum": 1
                    },
                    "custom_expiry_type": {
                        "description": "The unit of `custom_expiry_amount`: `days`, `weeks`, `months` or `years`. Required when `expiry_preset` is `custom`. No minutes or hours: a code that dies within the hour it was generated is a support ticket, not a feature.",
                        "anyOf": [
                            {
                                "$ref": "#/components/schemas/AccessCodeExpiryUnit"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    }
                },
                "required": [
                    "quantity",
                    "export_type",
                    "expiry_preset"
                ],
                "title": "BulkGenerateAccessCodesRequest"
            },
            "CancelPassWindowRequest": {
                "type": "object",
                "description": "What the cancellation does to the season-ticket holders of the window. Optional: with no body they are moved to the plan's next date on sale.",
                "properties": {
                    "series_holders": {
                        "description": "`substitute` (the default) moves season-ticket holders to the plan's next date on sale, keeping their season at the same length; `drop` removes the cancelled date from their season instead, leaves the rest standing, and reports what the date was worth per holder. Single-date holders are always moved where a date is on sale, and have their pass ended otherwise.",
                        "$ref": "#/components/schemas/SeriesLegSettlement"
                    }
                },
                "title": "CancelPassWindowRequest"
            },
            "CancellationReason": {
                "type": "string",
                "description": "Why a member said they were cancelling. A fixed list rather than a free field, because a creator reads the breakdown on the dashboard and a free answer cannot be counted; the optional sentence a member adds travels beside the case. The same ten reasons and \"Other\" show on the portal and in a connector's bot, in the member's own language, and the backing values are what the webhook and the API carry; each stays short enough to ride in a bot's callback data beside the action that carries it.\n",
                "enum": [
                    "too_expensive",
                    "not_using_enough",
                    "not_enough_content",
                    "content_not_expected",
                    "found_another_community",
                    "not_the_right_fit",
                    "taking_a_break",
                    "got_what_i_needed",
                    "technical_problems",
                    "signed_up_by_mistake",
                    "other"
                ],
                "title": "CancellationReason"
            },
            "CancellationReasonShareResource": {
                "type": "object",
                "description": "One reason members gave for cancelling over the window: its value, its label in the creator's language, how many gave it and its share of every reason given.",
                "properties": {
                    "reason": {
                        "type": "string",
                        "description": "The reason's value, such as `too_expensive`.",
                        "enum": [
                            "too_expensive",
                            "not_using_enough",
                            "not_enough_content",
                            "content_not_expected",
                            "found_another_community",
                            "not_the_right_fit",
                            "taking_a_break",
                            "got_what_i_needed",
                            "technical_problems",
                            "signed_up_by_mistake",
                            "other"
                        ]
                    },
                    "label": {
                        "type": "string",
                        "description": "The reason in the creator's language."
                    },
                    "count": {
                        "type": "integer",
                        "description": "How many members gave it."
                    },
                    "share_percent": {
                        "type": "number",
                        "description": "Its share of every reason given, in percent with one decimal."
                    }
                },
                "required": [
                    "reason",
                    "label",
                    "count",
                    "share_percent"
                ],
                "title": "CancellationReasonShareResource"
            },
            "CancellationRecordResource": {
                "type": "object",
                "description": "One cancellation screen a member reached: the reason they gave, their own words, the offer they were shown and whether they took it, and where they answered.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The record's id."
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project."
                    },
                    "subscription_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The membership the member was cancelling."
                    },
                    "member": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The member, present when the relation is loaded.",
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The member's project-scoped id."
                            },
                            "name": {
                                "type": "string",
                                "description": "The member's display name."
                            }
                        },
                        "required": [
                            "id",
                            "name"
                        ]
                    },
                    "plan": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The plan the membership was on, present when the relation is loaded; `null` when the membership is gone.",
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The plan's id."
                            },
                            "name": {
                                "type": "string",
                                "description": "The plan's name."
                            }
                        },
                        "required": [
                            "id",
                            "name"
                        ]
                    },
                    "reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The reason the member picked, or `null` when the project asked none.",
                        "enum": [
                            "too_expensive",
                            "not_using_enough",
                            "not_enough_content",
                            "content_not_expected",
                            "found_another_community",
                            "not_the_right_fit",
                            "taking_a_break",
                            "got_what_i_needed",
                            "technical_problems",
                            "signed_up_by_mistake",
                            "other",
                            null
                        ]
                    },
                    "feedback": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The sentence the member added, or `null`."
                    },
                    "offer_shown": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The offer the screen made: `pause`, `discount` or `return_coupon`; `null` when it made none.",
                        "enum": [
                            "pause",
                            "discount",
                            "return_coupon",
                            null
                        ]
                    },
                    "offer_taken": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The offer the member took, or `null`.",
                        "enum": [
                            "pause",
                            "discount",
                            "return_coupon",
                            null
                        ]
                    },
                    "surface": {
                        "type": "string",
                        "description": "Where the member answered: `portal` or `bot`.",
                        "enum": [
                            "portal",
                            "bot"
                        ]
                    },
                    "offer_resumes_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a pause the member took ends, ISO 8601; `null` otherwise."
                    },
                    "offer_resumed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When that pause ended and the member was let back in, ISO 8601; `null` until then."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the record was made, ISO 8601."
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "subscription_id",
                    "reason",
                    "feedback",
                    "offer_shown",
                    "offer_taken",
                    "surface",
                    "offer_resumes_at",
                    "offer_resumed_at",
                    "created_at"
                ],
                "title": "CancellationRecordResource"
            },
            "CancellationSurface": {
                "type": "string",
                "description": "Where a member answered the cancellation screen. Recorded so the creator can tell whether members leave from the portal or from a connector's bot, and so a bot's answer, which has no free text, is read for what it is.\n",
                "enum": [
                    "portal",
                    "bot"
                ],
                "title": "CancellationSurface"
            },
            "CheckoutAttemptResource": {
                "type": "object",
                "description": "One checkout a member started on the portal or in a bot: the member, the plan they were buying, the rail and where they started, when it started, when the hourly sweep counted it as stalled, when a charge finished it or another checkout superseded it, summed up as an outcome.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The checkout's id."
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project."
                    },
                    "member": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The member who started the checkout, present when the relation is loaded.",
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The member's project-scoped id."
                            },
                            "name": {
                                "type": "string",
                                "description": "The member's display name."
                            }
                        },
                        "required": [
                            "id",
                            "name"
                        ]
                    },
                    "plan": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The plan they were buying, present when the relation is loaded; `null` when the plan is gone.",
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The plan's id."
                            },
                            "name": {
                                "type": "string",
                                "description": "The plan's name."
                            }
                        },
                        "required": [
                            "id",
                            "name"
                        ]
                    },
                    "provider": {
                        "type": "string",
                        "description": "The rail the checkout opened on, as the payment methods list them; such as `stripe`.",
                        "enum": [
                            "stripe",
                            "paypal",
                            "skrill",
                            "coinpayments",
                            "paystack",
                            "razorpay",
                            "ceypay",
                            "platformcurrency",
                            "accesscode"
                        ]
                    },
                    "surface": {
                        "type": "string",
                        "description": "Where the member started: `portal` or `bot`.",
                        "enum": [
                            "portal",
                            "bot"
                        ]
                    },
                    "reference": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The order reference or session the rail was given, or `null` when the rail hands out none before the charge."
                    },
                    "method_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The payment method the checkout opened on, or `null` for a rail with no row of its own."
                    },
                    "outcome": {
                        "type": "string",
                        "description": "`open` while no charge has settled and the sweep has not counted it; `stalled` once the project's checkout window passed with no settled charge; `recovered` when a charge settled after it had stalled; `completed` when a charge settled before it could stall; `superseded` when it closed with no charge of its own, because the member paid through another checkout or already held a live membership when the sweep looked. One charge finishes one checkout and brings back one stalled checkout, so a member who tapped Pay three times and paid once has one `completed` and two `superseded`.",
                        "enum": [
                            "open",
                            "stalled",
                            "recovered",
                            "completed",
                            "superseded"
                        ]
                    },
                    "started_at": {
                        "type": "string",
                        "description": "When the member was handed the way to pay, ISO 8601."
                    },
                    "stalled_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the hourly sweep counted the checkout as stalled, ISO 8601; `null` until then."
                    },
                    "completed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a charge finished the checkout, ISO 8601; `null` while it is open or when it was superseded."
                    },
                    "superseded_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When another checkout of the member paid, or the sweep found them already a member, ISO 8601; `null` unless the outcome is `superseded`."
                    },
                    "payment_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The payment that finished the checkout, or `null` while it is open or when it was superseded."
                    },
                    "enrollment_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The stalled-checkout sequence passage the stall opened, or `null` when no sequence took the member."
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "provider",
                    "surface",
                    "reference",
                    "method_id",
                    "outcome",
                    "started_at",
                    "stalled_at",
                    "completed_at",
                    "superseded_at",
                    "payment_id",
                    "enrollment_id"
                ],
                "title": "CheckoutAttemptResource"
            },
            "ConnectorInstallationResource": {
                "type": "object",
                "description": "One connector installation of a project: its state and health, the platform's own account for it, and the timestamps of its life. Credentials and settings are never serialised.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The installation's id.",
                        "examples": [
                            "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40"
                        ]
                    },
                    "connector": {
                        "type": "string",
                        "description": "The connector's key.",
                        "examples": [
                            "example"
                        ]
                    },
                    "project_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The project the installation belongs to; null for a platform-scope presence.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "scope": {
                        "type": "string",
                        "description": "`project` for an installation a creator set up, `platform` for a presence Subscriby runs.",
                        "enum": [
                            "platform",
                            "project"
                        ],
                        "examples": [
                            "project"
                        ]
                    },
                    "role": {
                        "type": "string",
                        "description": "`live` for the installation that acts, `standby` for the spare the Disaster Recovery Program keeps.",
                        "enum": [
                            "live",
                            "standby"
                        ],
                        "examples": [
                            "live"
                        ]
                    },
                    "state": {
                        "type": "string",
                        "description": "`pending` (installed, nothing connected yet), `connected`, `degraded` (the health probe found something wrong), `revoked` (the platform withdrew it) or `disconnected` (the creator did).",
                        "enum": [
                            "pending",
                            "connected",
                            "degraded",
                            "revoked",
                            "disconnected"
                        ],
                        "examples": [
                            "connected"
                        ]
                    },
                    "state_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The connector's reason code for a `degraded` or `revoked` state; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "state_detail": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The connector's sentence about the state, in the creator's language; null when there is nothing to say.",
                        "examples": [
                            null
                        ]
                    },
                    "creator_actionable": {
                        "type": "boolean",
                        "description": "Whether the creator can fix the current state themselves.",
                        "examples": [
                            false
                        ]
                    },
                    "operational": {
                        "type": "boolean",
                        "description": "The one-word answer to \"can it act right now?\".",
                        "examples": [
                            true
                        ]
                    },
                    "external_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The platform's own id for the installation's account, such as a bot id; null while pending.",
                        "examples": [
                            "7123456789"
                        ]
                    },
                    "display_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The platform's display name for the account; null while pending.",
                        "examples": [
                            "Research Bot"
                        ]
                    },
                    "handle": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The platform's handle for the account, without a prefix; null while pending or where the platform has none.",
                        "examples": [
                            "research_bot"
                        ]
                    },
                    "avatar_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The account's avatar; null where none is known.",
                        "examples": [
                            null
                        ]
                    },
                    "health_checked_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the connector was last asked whether the installation still answers, ISO 8601.",
                        "examples": [
                            "2026-09-12T06:00:00Z"
                        ]
                    },
                    "doctor_ran_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the doctor last ran on the installation, ISO 8601; null before the first run.",
                        "examples": [
                            "2026-09-12T06:00:00Z"
                        ]
                    },
                    "doctor_healthy": {
                        "type": [
                            "boolean",
                            "null"
                        ],
                        "description": "Whether the last doctor report found every finding `ok`; null before the first run.",
                        "examples": [
                            true
                        ]
                    },
                    "connected_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the creator's credentials were bound, ISO 8601; null while pending.",
                        "examples": [
                            "2026-04-21T09:15:00Z"
                        ]
                    },
                    "verified_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the installation last answered a probe, ISO 8601.",
                        "examples": [
                            "2026-09-12T06:00:00Z"
                        ]
                    },
                    "revoked_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the platform withdrew the installation, ISO 8601; null unless revoked.",
                        "examples": [
                            null
                        ]
                    },
                    "disconnected_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the creator disconnected it, ISO 8601; null unless disconnected.",
                        "examples": [
                            null
                        ]
                    },
                    "uninstalled_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the connector was uninstalled from the project, ISO 8601; null while installed.",
                        "examples": [
                            null
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the installation was opened, ISO 8601.",
                        "examples": [
                            "2026-04-21T09:15:00Z"
                        ]
                    },
                    "capabilities": {
                        "type": "object",
                        "description": "Every capability the connector declares, keyed by capability, each with `enabled` (the project's switch for this installation) and `toggleable` (whether the switch can be turned off at all; `access_control`, `early_admission_hold`, `management_surface`, `portal_login` and `creator_registration` cannot).",
                        "additionalProperties": {
                            "type": "object",
                            "properties": {
                                "enabled": {
                                    "type": "boolean",
                                    "examples": [
                                        true
                                    ]
                                },
                                "toggleable": {
                                    "type": "boolean",
                                    "examples": [
                                        true
                                    ]
                                }
                            },
                            "required": [
                                "enabled",
                                "toggleable"
                            ]
                        }
                    },
                    "sales_paused": {
                        "type": "boolean",
                        "description": "Whether a connector outage is open on this installation, refusing every checkout of a plan that unlocks a place on it.",
                        "examples": [
                            false
                        ]
                    },
                    "outage": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The open outage while `sales_paused` is true, null otherwise.",
                        "examples": [
                            null
                        ],
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The outage's id."
                            },
                            "reason": {
                                "type": "string",
                                "description": "The connector's reason code for the outage, such as a revoked or regenerated token."
                            },
                            "started_at": {
                                "type": "string",
                                "description": "When the outage opened, ISO 8601."
                            }
                        },
                        "required": [
                            "id",
                            "reason",
                            "started_at"
                        ]
                    }
                },
                "required": [
                    "id",
                    "connector",
                    "project_id",
                    "scope",
                    "role",
                    "state",
                    "state_reason",
                    "state_detail",
                    "creator_actionable",
                    "operational",
                    "external_id",
                    "display_name",
                    "handle",
                    "avatar_url",
                    "health_checked_at",
                    "doctor_ran_at",
                    "doctor_healthy",
                    "connected_at",
                    "verified_at",
                    "revoked_at",
                    "disconnected_at",
                    "uninstalled_at",
                    "created_at",
                    "capabilities",
                    "sales_paused",
                    "outage"
                ],
                "title": "ConnectorInstallationResource"
            },
            "ConnectorListingResource": {
                "type": "object",
                "description": "One Connectors Marketplace card: the connector in its lane with its badges and, for a registered connector, its whole manifest and the declarative forms that connect and configure it. A roadmap card carries every manifest key null or empty.",
                "properties": {
                    "key": {
                        "type": "string",
                        "description": "The connector's key, the value the installation routes take as `{key}`.",
                        "examples": [
                            "example"
                        ]
                    },
                    "name": {
                        "type": "string",
                        "description": "The connector's display name.",
                        "examples": [
                            "Example"
                        ]
                    },
                    "vendor": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Who publishes the connector; null on a roadmap card.",
                        "examples": [
                            "Subscriby"
                        ]
                    },
                    "version": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The connector package's version; null on a roadmap card.",
                        "examples": [
                            "1.0.0"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "The lane: `available`, `beta`, `paused`, `in_development` or `coming_soon`.",
                        "enum": [
                            "available",
                            "beta",
                            "paused",
                            "in_development",
                            "coming_soon"
                        ],
                        "examples": [
                            "available"
                        ]
                    },
                    "status_label": {
                        "type": "string",
                        "description": "The lane heading the dashboard shows, in the token holder's language.",
                        "enum": [
                            "Available Now",
                            "Experimental",
                            "Paused",
                            "Under Development",
                            "Coming Soon"
                        ],
                        "examples": [
                            "Available Now"
                        ]
                    },
                    "installable": {
                        "type": "boolean",
                        "description": "Whether a creator may install the connector today: true for `available` and `beta` only.",
                        "examples": [
                            true
                        ]
                    },
                    "official": {
                        "type": "boolean",
                        "description": "Whether Subscriby publishes the connector itself.",
                        "examples": [
                            true
                        ]
                    },
                    "badges": {
                        "type": "array",
                        "description": "Facts the platform stamps, never the package's own claim: each `{key, label}` is `official` or `community` (who publishes it), `new` while the listing was added within the last sixty days, or `trending` for the connectors creators installed most in the last thirty days. Empty on a roadmap card.",
                        "items": {}
                    },
                    "installations": {
                        "type": "integer",
                        "description": "How many projects run the connector today, uninstalled rows excluded.",
                        "examples": [
                            1284
                        ]
                    },
                    "category": {
                        "type": "string",
                        "description": "The connector's family, such as `messaging`.",
                        "enum": [
                            "messaging",
                            "community",
                            "payments",
                            "productivity"
                        ],
                        "examples": [
                            "messaging"
                        ]
                    },
                    "tagline": {
                        "type": "string",
                        "description": "The one-line pitch on the card.",
                        "examples": [
                            "Sell access to channels and groups through your own bot."
                        ]
                    },
                    "overview": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The longer description; null on a roadmap card.",
                        "examples": [
                            "Connect a bot you created on the platform and Subscriby runs your membership there: …"
                        ]
                    },
                    "icon": {
                        "type": "string",
                        "description": "The icon slug the directory draws.",
                        "examples": [
                            "example"
                        ]
                    },
                    "eta": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a roadmap connector is expected, as a sentence; null once it is registered.",
                        "examples": [
                            null
                        ]
                    },
                    "links": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Where to read more; null on a roadmap card.",
                        "properties": {
                            "documentation": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The connector's guide on the docs site.",
                                "examples": [
                                    "https://docs.subscriby.net/connectors/example"
                                ]
                            },
                            "support": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Where to ask for help, a URL or a `mailto:`.",
                                "examples": [
                                    "mailto:support@subscriby.net"
                                ]
                            },
                            "privacy": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The platform's privacy policy.",
                                "examples": [
                                    "https://example.org/privacy"
                                ]
                            },
                            "terms": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The platform's terms of service.",
                                "examples": [
                                    "https://example.org/tos"
                                ]
                            },
                            "homepage": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The platform's home page.",
                                "examples": [
                                    "https://example.org"
                                ]
                            }
                        },
                        "required": [
                            "documentation",
                            "support",
                            "privacy",
                            "terms",
                            "homepage"
                        ]
                    },
                    "added_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The day the listing was added, `YYYY-MM-DD`; null on a roadmap card.",
                        "examples": [
                            "2025-04-21"
                        ]
                    },
                    "changelog_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Where the connector's changes are announced; null on a roadmap card.",
                        "examples": [
                            "https://www.subscriby.net/blog"
                        ]
                    },
                    "sign_in_required": {
                        "type": "boolean",
                        "description": "Whether connecting asks the creator to sign in on the platform rather than paste a credential.",
                        "examples": [
                            false
                        ]
                    },
                    "portal_cta": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The button the member portal shows to open the connector, or null when the connector has nowhere to open; the portal addresses it through the installation's start link.",
                        "properties": {
                            "label": {
                                "type": "string",
                                "description": "The button's text, translated.",
                                "examples": [
                                    "Open the app"
                                ]
                            },
                            "icon": {
                                "type": "string",
                                "description": "The button's icon slug.",
                                "examples": [
                                    "example"
                                ]
                            }
                        },
                        "required": [
                            "label",
                            "icon"
                        ]
                    },
                    "install_mode": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "How a creator connects it: `paste_credential` (the creator pastes a token the platform issued), `oauth` (the creator authorises an app) or `shared_platform` (Subscriby runs one shared presence; nothing to connect). Null on a roadmap card.",
                        "enum": [
                            "paste_credential",
                            "oauth",
                            "shared_platform",
                            null
                        ],
                        "examples": [
                            "paste_credential"
                        ]
                    },
                    "scopes": {
                        "type": "array",
                        "description": "`project` for an installation a creator sets up on a project, `platform` for a presence Subscriby itself runs on the connector.",
                        "items": {
                            "examples": [
                                "project"
                            ]
                        }
                    },
                    "resource_kinds": {
                        "type": "array",
                        "description": "The kinds of place the connector gates. Each carries `kind`, the creator-facing `label`, the `portal_label` members see, an `icon` slug, the `grant_mode` (`bearer_link`: a single-use link; `membership`: the connector admits the member itself; `role`: a role is granted; `creator_task`: the creator hands access over by hand), `supports_early_admission_hold` (whether a grant can be held ahead of a pass window), `upgrades_from` (the kind of the same connector a place of this kind can be an in-place upgrade of, or null) and `plan_kinds` (the shapes of plan a place can be sold under: `one_time`, `recurring`, `pass`, `pass_series`). A resource's `kind` on the Resources endpoints is `<key>:<kind>`.",
                        "items": {}
                    },
                    "capabilities": {
                        "type": "array",
                        "description": "The port families the connector implements: `messaging`, `broadcasts`, `access_control`, `early_admission_hold`, `support_relay`, `native_payments`, `portal_login`, `creator_registration`, `management_surface`, `copilot`, `recovery_probes`, `recovery_standby_installations`, `recovery_resource_standby`, `recovery_mirror`, `recovery_identity_relink`.",
                        "items": {
                            "examples": [
                                "messaging"
                            ]
                        }
                    },
                    "messaging": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The limits every message is checked against; null on a roadmap card.",
                        "properties": {
                            "max_length": {
                                "type": "integer",
                                "description": "The longest message body the platform delivers.",
                                "examples": [
                                    4096
                                ]
                            },
                            "buttons_per_row": {
                                "type": "integer",
                                "description": "How many buttons a keyboard row may hold.",
                                "examples": [
                                    8
                                ]
                            },
                            "max_buttons": {
                                "type": "integer",
                                "description": "How many buttons a message may carry in total.",
                                "examples": [
                                    100
                                ]
                            },
                            "callback_data_bytes": {
                                "type": "integer",
                                "description": "How many bytes a button's callback payload may hold.",
                                "examples": [
                                    64
                                ]
                            },
                            "supports_underline": {
                                "type": "boolean",
                                "description": "Whether underlined text renders.",
                                "examples": [
                                    true
                                ]
                            },
                            "supports_spoiler": {
                                "type": "boolean",
                                "description": "Whether spoiler text renders.",
                                "examples": [
                                    true
                                ]
                            },
                            "supports_files": {
                                "type": "boolean",
                                "description": "Whether files can be attached.",
                                "examples": [
                                    true
                                ]
                            }
                        },
                        "required": [
                            "max_length",
                            "buttons_per_row",
                            "max_buttons",
                            "callback_data_bytes",
                            "supports_underline",
                            "supports_spoiler",
                            "supports_files"
                        ]
                    },
                    "pacing": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The rate every bulk send is paced at; null on a roadmap card.",
                        "properties": {
                            "min_interval_microseconds": {
                                "type": "integer",
                                "description": "The shortest gap between two sends.",
                                "examples": [
                                    35000
                                ]
                            },
                            "burst": {
                                "type": "integer",
                                "description": "How many sends may go out before the gap applies.",
                                "examples": [
                                    30
                                ]
                            },
                            "per_recipient_interval_microseconds": {
                                "type": "integer",
                                "description": "The shortest gap between two sends to the same recipient.",
                                "examples": [
                                    1000000
                                ]
                            }
                        },
                        "required": [
                            "min_interval_microseconds",
                            "burst",
                            "per_recipient_interval_microseconds"
                        ]
                    },
                    "management_commands": {
                        "type": "array",
                        "description": "The core commands the connector's in-chat surface renders, such as `plan_create` or `broadcast`.",
                        "items": {
                            "examples": [
                                "project_create"
                            ]
                        }
                    },
                    "missing_commands": {
                        "type": "array",
                        "description": "The core commands the in-chat surface does not render; the Connectors tab shows the gaps from these.",
                        "items": {
                            "examples": [
                                "manage_connectors"
                            ]
                        }
                    },
                    "relay_modes": {
                        "type": "array",
                        "description": "How support conversations can be relayed on the connector, such as `owner_dm` or `forum_group`.",
                        "items": {
                            "type": "string",
                            "examples": [
                                "owner_dm"
                            ]
                        }
                    },
                    "recovery": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Which Disaster Recovery facets the connector implements; null on a roadmap card.",
                        "properties": {
                            "probes": {
                                "type": "boolean",
                                "description": "Whether the connector answers health probes.",
                                "examples": [
                                    true
                                ]
                            },
                            "standby_installations": {
                                "type": "boolean",
                                "description": "Whether a spare installation can be kept ready.",
                                "examples": [
                                    true
                                ]
                            },
                            "resource_standby": {
                                "type": "boolean",
                                "description": "Whether a spare place can be kept ready for a resource.",
                                "examples": [
                                    true
                                ]
                            },
                            "mirror": {
                                "type": "boolean",
                                "description": "Whether a standby can be mirrored from the live place.",
                                "examples": [
                                    true
                                ]
                            },
                            "identity_relink": {
                                "type": "boolean",
                                "description": "Whether a creator's account can be relinked after a loss.",
                                "examples": [
                                    true
                                ]
                            }
                        },
                        "required": [
                            "probes",
                            "standby_installations",
                            "resource_standby",
                            "mirror",
                            "identity_relink"
                        ]
                    },
                    "install_fields": {
                        "type": "array",
                        "description": "The declarative connect form, in order. Each field carries `name`, `type` (`text`, `secret`, `select`, `toggle`, `instructions`, `link`), a translated `label` and `help`, `required`, the validation `rules`, `options` for a select, a default `value`, the numbered walkthrough `steps` (with `:app` and `:button` placeholders for the app's name and the submit button's label) and `links` naming the text a renderer turns into a link.",
                        "items": {}
                    },
                    "settings_fields": {
                        "type": "array",
                        "description": "The declarative settings form, in the same shape as `install_fields`; its field names are the keys the settings endpoint accepts.",
                        "items": {}
                    }
                },
                "required": [
                    "key",
                    "name",
                    "vendor",
                    "version",
                    "status",
                    "status_label",
                    "installable",
                    "official",
                    "badges",
                    "installations",
                    "category",
                    "tagline",
                    "overview",
                    "icon",
                    "eta",
                    "links",
                    "added_at",
                    "changelog_url",
                    "sign_in_required",
                    "portal_cta",
                    "install_mode",
                    "scopes",
                    "resource_kinds",
                    "capabilities",
                    "messaging",
                    "pacing",
                    "management_commands",
                    "missing_commands",
                    "relay_modes",
                    "recovery",
                    "install_fields",
                    "settings_fields"
                ],
                "title": "ConnectorListingResource"
            },
            "CopilotAllowanceResource": {
                "type": "object",
                "description": "The month's free allowance of operator turns and member answers that every plan includes, with what is used and what is left.",
                "properties": {
                    "period_start": {
                        "type": "string",
                        "description": "The first day of the month the allowance counts, ISO 8601 date.",
                        "examples": [
                            "2026-10-01"
                        ]
                    },
                    "turns_used": {
                        "type": "integer",
                        "description": "Operator turns drawn from the allowance this month.",
                        "examples": [
                            12
                        ]
                    },
                    "turns_limit": {
                        "type": "integer",
                        "description": "Free operator turns the plan grants a month.",
                        "examples": [
                            25
                        ]
                    },
                    "turns_left": {
                        "type": "integer",
                        "description": "Free operator turns left this month, never below 0.",
                        "examples": [
                            13
                        ]
                    },
                    "answers_used": {
                        "type": "integer",
                        "description": "Member answers drawn from the allowance this month.",
                        "examples": [
                            40
                        ]
                    },
                    "answers_limit": {
                        "type": "integer",
                        "description": "Free member answers the plan grants a month.",
                        "examples": [
                            250
                        ]
                    },
                    "answers_left": {
                        "type": "integer",
                        "description": "Free member answers left this month, never below 0.",
                        "examples": [
                            210
                        ]
                    }
                },
                "required": [
                    "period_start",
                    "turns_used",
                    "turns_limit",
                    "turns_left",
                    "answers_used",
                    "answers_limit",
                    "answers_left"
                ],
                "title": "CopilotAllowanceResource"
            },
            "CopilotCreditBalanceResource": {
                "type": "object",
                "description": "The creator's Copilot Credits: the free and the paid part apart, what lapses next, and whether the pool is empty. Every amount is an integer in US cents.",
                "properties": {
                    "total_cents": {
                        "type": "integer",
                        "description": "Everything spendable right now, free and paid together.",
                        "examples": [
                            3250
                        ]
                    },
                    "free_cents": {
                        "type": "integer",
                        "description": "The free part: pack bonuses, promotions and goodwill, spent before the paid part.",
                        "examples": [
                            750
                        ]
                    },
                    "paid_cents": {
                        "type": "integer",
                        "description": "The paid part: what packs bought, which never lapses.",
                        "examples": [
                            2500
                        ]
                    },
                    "lapsing_cents": {
                        "type": "integer",
                        "description": "How much of the free part lapses next, 0 when nothing does.",
                        "examples": [
                            500
                        ]
                    },
                    "lapsing_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When `lapsing_cents` lapses, ISO 8601; null when nothing lapses.",
                        "examples": [
                            "2027-01-16T00:00:00+00:00"
                        ]
                    },
                    "exhausted": {
                        "type": "boolean",
                        "description": "Whether the pool has nothing left to draw on; the monthly allowance may still cover a turn.",
                        "examples": [
                            false
                        ]
                    }
                },
                "required": [
                    "total_cents",
                    "free_cents",
                    "paid_cents",
                    "lapsing_cents",
                    "lapsing_at",
                    "exhausted"
                ],
                "title": "CopilotCreditBalanceResource"
            },
            "CopilotCreditOverviewResource": {
                "type": "object",
                "description": "The creator's Copilot Credits in one object: the balance split into free and paid, this month's free allowance, this month's usage, the per-unit prices, the packs on sale and the auto top-up and cap. Every amount is an integer in US cents.",
                "properties": {
                    "balance": {
                        "description": "The pool: free and paid apart, what lapses next, whether it is empty.",
                        "$ref": "#/components/schemas/CopilotCreditBalanceResource"
                    },
                    "allowance": {
                        "description": "This month's free operator turns and member answers, used and left.",
                        "$ref": "#/components/schemas/CopilotAllowanceResource"
                    },
                    "turns_this_month": {
                        "type": "integer",
                        "description": "Operator turns this calendar month, from the allowance and the pool together.",
                        "examples": [
                            12
                        ]
                    },
                    "suggestions_this_month": {
                        "type": "integer",
                        "description": "Inbox reply suggestions this calendar month; no allowance covers these.",
                        "examples": [
                            4
                        ]
                    },
                    "answers_this_month": {
                        "type": "integer",
                        "description": "Member answers this calendar month, from the allowance and the pool together.",
                        "examples": [
                            40
                        ]
                    },
                    "paid_spent_this_month_cents": {
                        "type": "integer",
                        "description": "The paid credit drawn this calendar month, the figure the monthly cap is measured against.",
                        "examples": [
                            0
                        ]
                    },
                    "price_turn_cents": {
                        "type": "integer",
                        "description": "What one operator turn costs past the allowance; a turn past `long_turn_steps` tool steps, or on the Max tier, costs two.",
                        "examples": [
                            10
                        ]
                    },
                    "price_suggestion_cents": {
                        "type": "integer",
                        "description": "What one inbox reply suggestion costs.",
                        "examples": [
                            5
                        ]
                    },
                    "price_answer_cents": {
                        "type": "integer",
                        "description": "What one member answer costs past the allowance.",
                        "examples": [
                            1
                        ]
                    },
                    "long_turn_steps": {
                        "type": "integer",
                        "description": "The tool steps past which a turn counts twice.",
                        "examples": [
                            4
                        ]
                    },
                    "max_turn_steps": {
                        "type": "integer",
                        "description": "The tool steps at which a turn stops.",
                        "examples": [
                            8
                        ]
                    },
                    "low_balance_cents": {
                        "type": "integer",
                        "description": "The balance under which the low-balance notice is sent and the auto top-up buys.",
                        "examples": [
                            500
                        ]
                    },
                    "packs": {
                        "type": "array",
                        "description": "The packs on sale in this environment, smallest first.",
                        "items": {
                            "$ref": "#/components/schemas/CopilotCreditPackResource"
                        }
                    },
                    "settings": {
                        "description": "The auto top-up and the monthly cap, as `PATCH /v1/me/copilot-credits/settings` writes them.",
                        "$ref": "#/components/schemas/CopilotCreditSettingsResource"
                    }
                },
                "required": [
                    "balance",
                    "allowance",
                    "turns_this_month",
                    "suggestions_this_month",
                    "answers_this_month",
                    "paid_spent_this_month_cents",
                    "price_turn_cents",
                    "price_suggestion_cents",
                    "price_answer_cents",
                    "long_turn_steps",
                    "max_turn_steps",
                    "low_balance_cents",
                    "packs",
                    "settings"
                ],
                "title": "CopilotCreditOverviewResource"
            },
            "CopilotCreditPack": {
                "type": "string",
                "description": "The four Copilot Credits packs a creator can buy, from the smallest to the largest. Each pack is one Stripe price; what it pays into the ledger and the free bonus that comes with it are configuration, read here so a price change never touches code. The bonus is a free grant, never money on Stripe.\n",
                "enum": [
                    "starter",
                    "regular",
                    "plus",
                    "max"
                ],
                "title": "CopilotCreditPack"
            },
            "CopilotCreditPackCheckoutResource": {
                "type": "object",
                "description": "A pack purchase opened for the creator: which pack, what it grants, and the Stripe Checkout URL that takes the payment. The credit lands when Stripe reports the session paid, never before.",
                "properties": {
                    "pack": {
                        "type": "string",
                        "description": "The pack: `starter`, `regular`, `plus` or `max`.",
                        "enum": [
                            "starter",
                            "regular",
                            "plus",
                            "max"
                        ],
                        "examples": [
                            "regular"
                        ]
                    },
                    "label": {
                        "type": "string",
                        "description": "The pack's name as the dashboard shows it.",
                        "enum": [
                            "Starter Pack",
                            "Regular Pack",
                            "Plus Pack",
                            "Max Pack"
                        ],
                        "examples": [
                            "Regular Pack"
                        ]
                    },
                    "paid_cents": {
                        "type": "integer",
                        "description": "What the creator pays, before tax.",
                        "examples": [
                            2500
                        ]
                    },
                    "bonus_cents": {
                        "type": "integer",
                        "description": "The free credit the pack adds on top.",
                        "examples": [
                            250
                        ]
                    },
                    "checkout_url": {
                        "type": "string",
                        "description": "The Stripe Checkout page to send the creator to; it expires after 24 hours and pays with their card, saving it for the auto top-up.",
                        "examples": [
                            "https://checkout.stripe.com/c/pay/cs_live_…"
                        ]
                    }
                },
                "required": [
                    "pack",
                    "label",
                    "paid_cents",
                    "bonus_cents",
                    "checkout_url"
                ],
                "title": "CopilotCreditPackCheckoutResource"
            },
            "CopilotCreditPackResource": {
                "description": "A pack of Copilot Credits that can be bought: what it costs, the free bonus it adds and the total it grants. Amounts are integers in US cents.",
                "anyOf": [
                    {
                        "type": "object",
                        "properties": {
                            "pack": {
                                "type": "string",
                                "description": "The pack: `starter`, `regular`, `plus` or `max`; the value to send when buying one or choosing the auto top-up.",
                                "enum": [
                                    "starter",
                                    "regular",
                                    "plus",
                                    "max"
                                ],
                                "examples": [
                                    "starter"
                                ]
                            },
                            "label": {
                                "type": "string",
                                "description": "The pack's name as the dashboard shows it.",
                                "enum": [
                                    "Starter Pack",
                                    "Regular Pack",
                                    "Plus Pack",
                                    "Max Pack"
                                ],
                                "examples": [
                                    "Starter Pack"
                                ]
                            },
                            "paid_cents": {
                                "type": "integer",
                                "description": "What the creator pays, before tax.",
                                "examples": [
                                    1000
                                ]
                            },
                            "bonus_cents": {
                                "type": "integer",
                                "description": "The free credit the pack adds on top, 0 on the smallest.",
                                "examples": [
                                    0
                                ]
                            },
                            "total_cents": {
                                "type": "integer",
                                "description": "What the pack grants in all, paid and bonus together.",
                                "examples": [
                                    1000
                                ]
                            }
                        },
                        "required": [
                            "pack",
                            "label",
                            "paid_cents",
                            "bonus_cents",
                            "total_cents"
                        ]
                    },
                    {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "minItems": 0,
                        "maxItems": 0
                    }
                ],
                "title": "CopilotCreditPackResource"
            },
            "CopilotCreditSettingsResource": {
                "type": "object",
                "description": "The creator's choices for their Copilot Credits: which pack the auto top-up buys and under which balance, and how much paid credit the Copilot may spend in a month. Amounts are integers in US cents.",
                "properties": {
                    "auto_topup_pack": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The pack the auto top-up buys when the balance falls under `auto_topup_below_cents`; null when the auto top-up is off.",
                        "enum": [
                            "starter",
                            "regular",
                            "plus",
                            "max",
                            null
                        ],
                        "examples": [
                            "regular"
                        ]
                    },
                    "auto_topup_pack_label": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "That pack's name, or null.",
                        "enum": [
                            "Starter Pack",
                            "Regular Pack",
                            "Plus Pack",
                            "Max Pack",
                            null
                        ],
                        "examples": [
                            "Regular Pack"
                        ]
                    },
                    "auto_topup_below_cents": {
                        "type": "integer",
                        "description": "The balance under which the auto top-up buys, 100 to 10,000.",
                        "examples": [
                            500
                        ]
                    },
                    "monthly_spend_cap_cents": {
                        "type": "integer",
                        "description": "The paid credit the Copilot may draw in a calendar month before it stops, 0 to 1,000,000; the free allowance is never capped.",
                        "examples": [
                            2000
                        ]
                    },
                    "auto_topup_paused_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a failed charge paused the auto top-up, ISO 8601; null while it runs. Saving the settings again resumes it.",
                        "examples": [
                            null
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the settings last changed, ISO 8601.",
                        "examples": [
                            "2026-10-12T09:20:00+00:00"
                        ]
                    }
                },
                "required": [
                    "auto_topup_pack",
                    "auto_topup_pack_label",
                    "auto_topup_below_cents",
                    "monthly_spend_cap_cents",
                    "auto_topup_paused_at",
                    "updated_at"
                ],
                "title": "CopilotCreditSettingsResource"
            },
            "CopilotCreditStatementEntryResource": {
                "type": "object",
                "description": "One line of the creator's Copilot Credits statement: a pack bought, its bonus, a promotion, goodwill, a month's usage of one kind, a refund or a lapse. Amounts are integers in US cents, positive for credit and negative for debit.",
                "properties": {
                    "kind": {
                        "type": "string",
                        "description": "What the line is: `purchase`, `bonus`, `welcome`, `promotion`, `goodwill`, `usage`, `refund` or `lapsed`.",
                        "enum": [
                            "purchase",
                            "bonus",
                            "welcome",
                            "promotion",
                            "goodwill",
                            "usage",
                            "refund",
                            "lapsed"
                        ],
                        "examples": [
                            "usage"
                        ]
                    },
                    "kind_label": {
                        "type": "string",
                        "description": "The kind as the Billing statement shows it.",
                        "enum": [
                            "Pack Bought",
                            "Pack Bonus",
                            "Welcome Credit",
                            "Promotion",
                            "Goodwill",
                            "Copilot Usage",
                            "Refund",
                            "Lapsed"
                        ],
                        "examples": [
                            "Copilot Usage"
                        ]
                    },
                    "cents": {
                        "type": "integer",
                        "description": "The amount: positive for credit granted, negative for credit spent, refunded or lapsed.",
                        "examples": [
                            -120
                        ]
                    },
                    "at": {
                        "type": "string",
                        "description": "When the line is dated, ISO 8601; a usage line is dated the first of its month.",
                        "examples": [
                            "2026-10-01T00:00:00+00:00"
                        ]
                    },
                    "label": {
                        "type": "string",
                        "description": "The line's description as the Billing statement shows it.",
                        "examples": [
                            "Copilot Turns, October 2026"
                        ]
                    },
                    "expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a free grant lapses, ISO 8601; null for anything else.",
                        "examples": [
                            null
                        ]
                    },
                    "units": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "On a usage line, how many units the month's cents paid for; null otherwise.",
                        "examples": [
                            12
                        ]
                    },
                    "usage_kind": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "On a usage line, `operator_turn`, `inbox_suggestion` or `member_answer`; null otherwise.",
                        "enum": [
                            "operator_turn",
                            "inbox_suggestion",
                            "member_answer",
                            null
                        ],
                        "examples": [
                            "operator_turn"
                        ]
                    },
                    "usage_kind_label": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "That kind as the dashboard names it, or null.",
                        "enum": [
                            "Copilot Turns",
                            "Reply Suggestions",
                            "Member Answers",
                            null
                        ],
                        "examples": [
                            "Copilot Turns"
                        ]
                    }
                },
                "required": [
                    "kind",
                    "kind_label",
                    "cents",
                    "at",
                    "label",
                    "expires_at",
                    "units",
                    "usage_kind",
                    "usage_kind_label"
                ],
                "title": "CopilotCreditStatementEntryResource"
            },
            "CouponDiscountType": {
                "type": "string",
                "enum": [
                    "percentage",
                    "fixed"
                ],
                "title": "CouponDiscountType"
            },
            "CouponResource": {
                "type": "object",
                "description": "A coupon: one code many subscribers can redeem for money off at checkout, with its discount, limits, redemption tally and sales window.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The coupon's id.",
                        "examples": [
                            "4b9d3e08-a1f6-4275-9c83-7e01d6a2f594"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the coupon belongs to; codes are unique within a project, not across projects.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "code": {
                        "type": "string",
                        "description": "The code subscribers type at checkout, stored and matched in upper case.",
                        "examples": [
                            "BLACKFRIDAY"
                        ]
                    },
                    "name": {
                        "type": "string",
                        "description": "A creator-facing label, never shown to subscribers.",
                        "examples": [
                            "Black Friday 2026"
                        ]
                    },
                    "discount": {
                        "type": "object",
                        "description": "What comes off the price.",
                        "properties": {
                            "type": {
                                "type": "string",
                                "description": "`percentage` or `fixed`.",
                                "enum": [
                                    "percentage",
                                    "fixed"
                                ],
                                "examples": [
                                    "percentage"
                                ]
                            },
                            "value": {
                                "type": "string",
                                "description": "A decimal string with four places: `\"25.0000\"` for 25% off, `\"10.0000\"` for ten of the coupon's currency. Parse it as a decimal, never a float.",
                                "examples": [
                                    "25.0000"
                                ]
                            },
                            "currency_id": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The currency a `fixed` discount is denominated in; null on a `percentage` coupon, which applies to a plan in any currency.",
                                "examples": [
                                    null
                                ]
                            },
                            "currency": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "That currency's ISO 4217 code, present only when the relation is loaded: on a single read, a create and an update, not on every list row.",
                                "examples": [
                                    null
                                ]
                            }
                        },
                        "required": [
                            "type",
                            "value",
                            "currency_id"
                        ]
                    },
                    "duration": {
                        "type": "string",
                        "description": "Always `once`: only first-payment discounts exist today.",
                        "enum": [
                            "once",
                            "forever"
                        ],
                        "examples": [
                            "once"
                        ]
                    },
                    "limits": {
                        "type": "object",
                        "description": "How often and on what the code may be used.",
                        "properties": {
                            "max_redemptions": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "The total cap across everyone; null for unlimited.",
                                "examples": [
                                    500
                                ]
                            },
                            "max_redemptions_per_user": {
                                "type": "integer",
                                "description": "How many times one member may redeem the code.",
                                "examples": [
                                    1
                                ]
                            },
                            "minimum_amount": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The order floor, in the plan's own currency; null for none.",
                                "examples": [
                                    null
                                ]
                            }
                        },
                        "required": [
                            "max_redemptions",
                            "max_redemptions_per_user",
                            "minimum_amount"
                        ]
                    },
                    "redemptions": {
                        "type": "object",
                        "description": "How far the cap has been used.",
                        "properties": {
                            "count": {
                                "type": "integer",
                                "description": "Settled redemptions so far.",
                                "examples": [
                                    137
                                ]
                            },
                            "remaining": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "Derived, not stored: the cap minus settled redemptions and reservations whose hold has not expired, so an in-flight checkout is already counted and an abandoned one gives its slot back. Prefer it over your own subtraction, which will disagree. Null when uncapped.",
                                "examples": [
                                    363
                                ]
                            },
                            "exhausted": {
                                "type": "boolean",
                                "description": "Whether nothing remains under the cap.",
                                "examples": [
                                    false
                                ]
                            }
                        },
                        "required": [
                            "count",
                            "remaining",
                            "exhausted"
                        ]
                    },
                    "window": {
                        "type": "object",
                        "description": "When the code can be redeemed.",
                        "properties": {
                            "starts_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "When redemption opens, ISO 8601; null for immediately.",
                                "examples": [
                                    "2026-11-27T00:00:00+00:00"
                                ]
                            },
                            "expires_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "When redemption closes, ISO 8601; null for never.",
                                "examples": [
                                    "2026-12-01T00:00:00+00:00"
                                ]
                            }
                        },
                        "required": [
                            "starts_at",
                            "expires_at"
                        ]
                    },
                    "plan_ids": {
                        "type": "object",
                        "description": "The plans the code is restricted to. An empty array means **every** plan in the project, including plans added later, not no plans.",
                        "additionalProperties": {}
                    },
                    "active": {
                        "type": "boolean",
                        "description": "The creator's on/off switch. Not the same as redeemable.",
                        "examples": [
                            true
                        ]
                    },
                    "redeemable": {
                        "type": "boolean",
                        "description": "The combined answer: switched on, inside its window, not exhausted. Read this rather than `active` to know whether the code applies right now.",
                        "examples": [
                            true
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the coupon was created, ISO 8601.",
                        "examples": [
                            "2026-11-20T09:14:02+00:00"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it last changed, ISO 8601.",
                        "examples": [
                            "2026-11-24T16:41:11+00:00"
                        ]
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "code",
                    "name",
                    "discount",
                    "duration",
                    "limits",
                    "redemptions",
                    "window",
                    "plan_ids",
                    "active",
                    "redeemable",
                    "created_at",
                    "updated_at"
                ],
                "title": "CouponResource"
            },
            "CreatorTaskFilter": {
                "type": "string",
                "description": "Which creator tasks a list shows. `Open` is the working list: tasks not yet done whose grant still stands, so a purchase that ended drops out without anyone marking it. `Completed` is the record; `All` is both.\n",
                "enum": [
                    "open",
                    "completed",
                    "all"
                ],
                "title": "CreatorTaskFilter"
            },
            "CreatorTaskResource": {
                "type": "object",
                "description": "A creator task: a grant no connector can give, waiting for the creator to hand the perk over by hand.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The task's id, the value the complete endpoint takes and `creator_task.opened` carries as `task_id`.",
                        "examples": [
                            "9e4b2c71-3d58-4a6f-b0e2-7c1d5f8a9b34"
                        ]
                    },
                    "grant_id": {
                        "type": "string",
                        "description": "The access-ledger row the task belongs to; read it among the subscription's grants, where its `mode` is `creator_task`.",
                        "examples": [
                            "7d1c3e9a-2b64-4f0e-9a58-3c6b1d8e2f47"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the task belongs to.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "subscription_id": {
                        "type": "string",
                        "description": "The purchase that entitles the member to the perk.",
                        "examples": [
                            "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                        ]
                    },
                    "subscriber_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The member who is owed the perk.",
                        "examples": [
                            "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                        ]
                    },
                    "resource_id": {
                        "type": "string",
                        "description": "The manual resource to hand over.",
                        "examples": [
                            "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6"
                        ]
                    },
                    "resource_title": {
                        "type": "string",
                        "description": "That resource's title, so an integration need not fetch it to say which perk.",
                        "examples": [
                            "Welcome packet"
                        ]
                    },
                    "instructions": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The sentence the dashboard shows the creator, in the creator's language.",
                        "examples": [
                            "Give Ada Lovelace access to Welcome packet."
                        ]
                    },
                    "due_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The window's start for a dated pass, ISO 8601; null for continuous access.",
                        "examples": [
                            null
                        ]
                    },
                    "completed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the task was marked done, ISO 8601; null while open.",
                        "examples": [
                            null
                        ]
                    },
                    "completed_by_user_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The creator who marked it done; null while open.",
                        "examples": [
                            null
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the task opened, ISO 8601.",
                        "examples": [
                            "2026-09-12T10:05:30Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "grant_id",
                    "project_id",
                    "subscription_id",
                    "subscriber_id",
                    "resource_id",
                    "resource_title",
                    "instructions",
                    "due_at",
                    "completed_at",
                    "completed_by_user_id",
                    "created_at"
                ],
                "title": "CreatorTaskResource"
            },
            "DashboardPeriod": {
                "type": "string",
                "description": "The preset reporting windows a dashboard, export or analytics call can ask for. Presets are anchored on \"now\" so the same preset means the same thing on every surface; an explicit from/to pair on `ReportWindow` overrides the preset. Unknown input falls back to thirty days rather than failing, because a period from a query string or an MCP argument is never worth a 422.\n",
                "enum": [
                    "7d",
                    "14d",
                    "30d",
                    "60d",
                    "90d",
                    "1y",
                    "mtd",
                    "qtd",
                    "ytd",
                    "all"
                ],
                "title": "DashboardPeriod"
            },
            "DoctorReportResource": {
                "type": "object",
                "description": "A connector doctor report: one finding for the installation, then one per resource it gates.",
                "properties": {
                    "installation_id": {
                        "type": "string",
                        "description": "The installation the doctor ran on.",
                        "examples": [
                            "3b8f0c6e-2d41-4a97-9e5f-1c7d6b2a8e40"
                        ]
                    },
                    "connector": {
                        "type": "string",
                        "description": "The connector's key.",
                        "examples": [
                            "example"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the installation belongs to.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "ran_at": {
                        "type": "string",
                        "description": "When the report was produced, ISO 8601.",
                        "examples": [
                            "2026-09-12T10:07:00Z"
                        ]
                    },
                    "healthy": {
                        "type": "boolean",
                        "description": "True when every finding is `ok`.",
                        "examples": [
                            false
                        ]
                    },
                    "critical": {
                        "type": "integer",
                        "description": "How many findings are `critical`.",
                        "examples": [
                            1
                        ]
                    },
                    "warnings": {
                        "type": "integer",
                        "description": "How many findings are `warning`.",
                        "examples": [
                            0
                        ]
                    },
                    "findings": {
                        "type": "array",
                        "description": "The findings, the installation's first. Each carries `key` (`installation`, or `resource:<id>`), `kind` (`installation` or `resource`), `severity` (`ok`, `warning`, `critical`) with its `severity_label`, the `subject` (the account or the place), the connector's own `state` word, a `message` in the creator's language, `creator_actionable` (whether the creator can fix it), `fix_url` (where, or null) and `resource_id` (null for the installation finding). A resource the connector has no place for is a `warning`, never silence.",
                        "items": {}
                    }
                },
                "required": [
                    "installation_id",
                    "connector",
                    "project_id",
                    "ran_at",
                    "healthy",
                    "critical",
                    "warnings",
                    "findings"
                ],
                "title": "DoctorReportResource"
            },
            "GroupResource": {
                "type": "object",
                "description": "A group: a named permission bundle a team shares between several collaborators, each of whom may be in several groups.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The group's id.",
                        "examples": [
                            "1f68d92a-04c5-4e83-97b1-3d6a05e2f847"
                        ]
                    },
                    "team_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The team the group belongs to.",
                        "examples": [
                            "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86"
                        ]
                    },
                    "code": {
                        "type": "string",
                        "description": "The machine name, unique within the team and immutable after creation, because permissions are addressed by it.",
                        "examples": [
                            "ops"
                        ]
                    },
                    "name": {
                        "type": "string",
                        "description": "The display name.",
                        "examples": [
                            "Ops"
                        ]
                    },
                    "permissions": {
                        "type": "array",
                        "description": "The permission codes the group grants. Returned when the group is read individually or after a write, omitted from list responses so a listing stays one query.",
                        "items": {
                            "type": "string",
                            "description": "A permission code, as `/abilities.json` lists them.",
                            "examples": [
                                "project:view-any"
                            ]
                        }
                    },
                    "member_ids": {
                        "type": "array",
                        "description": "The users in the group. Returned after a member sync, omitted elsewhere.",
                        "items": {
                            "type": "string",
                            "description": "A user id.",
                            "examples": [
                                "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                            ]
                        }
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the group was created, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "team_id",
                    "code",
                    "name",
                    "created_at"
                ],
                "title": "GroupResource"
            },
            "InviteTeamMemberRequest": {
                "type": "object",
                "description": "Who to invite and as what. An invitation names an email rather than a user, because the invitee may not have an account yet.",
                "properties": {
                    "email": {
                        "type": "string",
                        "format": "email",
                        "description": "The invitee's email address, up to 255 characters. They receive an invitation message with a link; the membership appears when they accept.",
                        "maxLength": 255
                    },
                    "role": {
                        "type": "string",
                        "description": "A role **code** on that team, such as `support-agent`, not a role id. Create it first if it does not exist; an unknown code is refused.",
                        "maxLength": 255
                    }
                },
                "required": [
                    "email",
                    "role"
                ],
                "title": "InviteTeamMemberRequest"
            },
            "KnowledgeAudience": {
                "type": "string",
                "description": "Who Subscriby Copilot may be answering when it reads a Knowledge entry. Every entry serves the creator's own surfaces, the operator and the inbox suggester. Only an entry marked for members serves the member-facing answerer, in the project bot and on the portal, so a creator's private notes never reach a member by construction: the member search filters on this value and nothing else can widen it. Both cases are declared from the first migration because the column is an enum whose check constraint cannot be widened once it exists.\n",
                "enum": [
                    "team",
                    "members"
                ],
                "title": "KnowledgeAudience"
            },
            "KnowledgeEntryKind": {
                "type": "string",
                "description": "The two shapes a Knowledge entry takes: a question with its answer, or an uploaded document. A question is written on the Knowledge page and is one passage; a document is a file whose text is cut into passages when it is uploaded. Both cases are declared from the first migration because `knowledge_entries.kind` is an enum whose check constraint cannot be widened once it exists.\n",
                "enum": [
                    "question",
                    "document"
                ],
                "title": "KnowledgeEntryKind"
            },
            "KnowledgeEntryResource": {
                "type": "object",
                "description": "One thing a project taught Subscriby Copilot: a question with its answer or a document, with who may be answered from it and how it was indexed.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The entry's id.",
                        "examples": [
                            "3b7e4d2a-9c1f-4a6b-8d5e-2f7c9a1b3e4d"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project that taught it.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "kind": {
                        "type": "string",
                        "description": "`question` (a question with its answer) or `document` (a plain-text or Markdown guide). Fixed once the entry exists.",
                        "enum": [
                            "question",
                            "document"
                        ],
                        "examples": [
                            "question"
                        ]
                    },
                    "kind_label": {
                        "type": "string",
                        "description": "The kind as the dashboard labels it.",
                        "enum": [
                            "Question & Answer",
                            "Document"
                        ],
                        "examples": [
                            "Question & Answer"
                        ]
                    },
                    "audience": {
                        "type": "string",
                        "description": "`members` (members may be answered from it in the inbox, the bot and the portal, and the team reads it too) or `team` (the creator's own surfaces only: the suggested reply, the panel and the platform bot).",
                        "enum": [
                            "team",
                            "members"
                        ],
                        "examples": [
                            "members"
                        ]
                    },
                    "audience_label": {
                        "type": "string",
                        "description": "The audience as the dashboard labels it.",
                        "enum": [
                            "Team Only",
                            "Members & Team"
                        ],
                        "examples": [
                            "Members & Team"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "`ready` once the passages are in the index, `indexing` while they are cut, `failed` when the text could not be read.",
                        "enum": [
                            "indexing",
                            "ready",
                            "failed"
                        ],
                        "examples": [
                            "ready"
                        ]
                    },
                    "status_label": {
                        "type": "string",
                        "description": "The status as the dashboard labels it.",
                        "enum": [
                            "Indexing",
                            "Ready",
                            "Failed"
                        ],
                        "examples": [
                            "Ready"
                        ]
                    },
                    "title": {
                        "type": "string",
                        "description": "The question, or the document's name as the creator wants it shown; written at the head of every passage.",
                        "examples": [
                            "When does my membership renew?"
                        ]
                    },
                    "body": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The text the Copilot reads from: the answer, or the document's text. Carried on a single read and after a write; `null` on a list row.",
                        "examples": [
                            null
                        ]
                    },
                    "file_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The uploaded file's name for a document saved from the dashboard; `null` for a question or a document sent as text.",
                        "examples": [
                            null
                        ]
                    },
                    "file_size": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The uploaded file's size in bytes, or `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "mime": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The uploaded file's media type, or `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "chunk_count": {
                        "type": "integer",
                        "description": "How many passages the text was cut into.",
                        "examples": [
                            1
                        ]
                    },
                    "characters": {
                        "type": "integer",
                        "description": "How many characters the text holds.",
                        "examples": [
                            64
                        ]
                    },
                    "failure": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why indexing failed when `status` is `failed`; otherwise `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "indexed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the passages last reached the index, ISO 8601; `null` until the first time.",
                        "examples": [
                            "2026-10-19T16:02:11+00:00"
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the entry was created, ISO 8601.",
                        "examples": [
                            "2026-10-19T16:02:11+00:00"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the entry last changed, ISO 8601.",
                        "examples": [
                            "2026-10-19T16:02:11+00:00"
                        ]
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "kind",
                    "kind_label",
                    "audience",
                    "audience_label",
                    "status",
                    "status_label",
                    "title",
                    "body",
                    "file_name",
                    "file_size",
                    "mime",
                    "chunk_count",
                    "characters",
                    "failure",
                    "indexed_at",
                    "created_at",
                    "updated_at"
                ],
                "title": "KnowledgeEntryResource"
            },
            "Locale": {
                "type": "string",
                "enum": [
                    "en",
                    "fr",
                    "es",
                    "it",
                    "hi",
                    "bn",
                    "de",
                    "pt",
                    "tr",
                    "si"
                ],
                "title": "Locale"
            },
            "MeResource": {
                "type": "object",
                "description": "The caller's account: who the token belongs to, the team it is scoped to, every team they hold, the platform plan and its capabilities, the accounts linked on the connectors and where alerts go.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The creator's user id.",
                        "examples": [
                            "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                        ]
                    },
                    "name": {
                        "type": "string",
                        "description": "The creator's name.",
                        "examples": [
                            "Ada Lovelace"
                        ]
                    },
                    "email": {
                        "type": "string",
                        "description": "The creator's email address.",
                        "examples": [
                            "ada@example.com"
                        ]
                    },
                    "locale": {
                        "type": "string",
                        "description": "The creator's language, as a locale code.",
                        "examples": [
                            "en"
                        ]
                    },
                    "email_verified": {
                        "type": "boolean",
                        "description": "Whether the email address has been verified.",
                        "examples": [
                            true
                        ]
                    },
                    "plan": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The platform tier's type (`free`, `starter`, `growth`, …) while the subscription is active, or null without one. It is the plan that gates what the creator can do, not the one still being billed while past due.",
                        "examples": [
                            "growth"
                        ]
                    },
                    "capabilities": {
                        "type": "object",
                        "description": "Every capability the tiers can grant, each true when the plan or an active add-on grants it: `no_branding`, `time_limited_passes`, `coupons`, `free_plans`, `teams`, `disaster_recovery_prevention`, `multi_connector`, `referrals`, `retention`, `custom_domain`. The set is fixed by the platform, so a client can render toggles from the keys.",
                        "additionalProperties": {
                            "type": "boolean",
                            "description": "Whether the plan or an active add-on grants the capability.",
                            "examples": [
                                true
                            ]
                        }
                    },
                    "current_team": {
                        "type": [
                            "array",
                            "null"
                        ],
                        "description": "The team the token is scoped to, when the creator still belongs to it; null when the token carries no team scope. Its id is the value every project call resolves against.",
                        "items": {}
                    },
                    "teams": {
                        "type": "array",
                        "description": "Every team the creator owns or is a member of, the same list as the teams endpoint.",
                        "items": {}
                    },
                    "identities": {
                        "type": "array",
                        "description": "The accounts linked on the connectors, the same list as the identities endpoint.",
                        "items": {}
                    },
                    "alert_destinations": {
                        "type": "array",
                        "description": "Where each alert class goes, the same list as the alert destinations endpoint.",
                        "items": {}
                    },
                    "alert_destinations_default": {
                        "type": "boolean",
                        "description": "True while no destination has been written and the default routing applies: every class to the primary connected account, critical classes by email.",
                        "examples": [
                            true
                        ]
                    },
                    "unread_notifications": {
                        "type": "integer",
                        "description": "How many Notifications Center entries the creator has not opened, the number on the sidebar entry.",
                        "examples": [
                            3
                        ]
                    },
                    "partner_code": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The creator's Partner Program code once Subscriby approved them as a partner; null before. The full standing is at `GET /v1/me/partner`.",
                        "examples": [
                            "ADA7Q2X"
                        ]
                    },
                    "partner_link": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The web link that code rides on, the address a partner hands out; null until approved.",
                        "examples": [
                            "https://app.subscriby.net/r/ADA7Q2X"
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the account was created, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "name",
                    "email",
                    "locale",
                    "email_verified",
                    "plan",
                    "capabilities",
                    "current_team",
                    "teams",
                    "identities",
                    "alert_destinations",
                    "alert_destinations_default",
                    "unread_notifications",
                    "partner_code",
                    "partner_link",
                    "created_at"
                ],
                "title": "MeResource"
            },
            "MemberIdentityResource": {
                "type": "object",
                "description": "One of a member's connected connector accounts: how and when it was connected, whether the project reaches it first, and what the platform calls the person. Storage references and installation ids never leave.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The link's id, the value the disconnect endpoint takes.",
                        "examples": [
                            "6a1f0c3e-2d4b-4e8a-9c7d-1b5e3f9a2c4d"
                        ]
                    },
                    "connector": {
                        "type": "string",
                        "description": "The connector the account is on, by key.",
                        "examples": [
                            "telegram"
                        ]
                    },
                    "source": {
                        "type": "string",
                        "description": "How the account was connected: `bot` (through the project's bot), `portal` (from the portal's Account & Recovery screen), `handshake`, `adopted` or `backfill`.",
                        "enum": [
                            "bot",
                            "portal",
                            "handshake",
                            "adopted",
                            "backfill"
                        ],
                        "examples": [
                            "handshake"
                        ]
                    },
                    "preferred": {
                        "type": "boolean",
                        "description": "Whether the project reaches the member through this account first.",
                        "examples": [
                            true
                        ]
                    },
                    "notify": {
                        "type": "boolean",
                        "description": "Whether the member receives the project's messages on this account.",
                        "examples": [
                            false
                        ]
                    },
                    "external_id": {
                        "type": "string",
                        "description": "The platform's own id for the account.",
                        "examples": [
                            "123456789"
                        ]
                    },
                    "display_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the platform calls the person.",
                        "examples": [
                            "Jane Doe"
                        ]
                    },
                    "username": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The account's handle when the platform has one; null otherwise.",
                        "examples": [
                            "janedoe"
                        ]
                    },
                    "linked_at": {
                        "type": "string",
                        "description": "When the account was connected, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "connector",
                    "source",
                    "preferred",
                    "notify",
                    "external_id",
                    "display_name",
                    "username",
                    "linked_at"
                ],
                "title": "MemberIdentityResource"
            },
            "MemberResource": {
                "type": "object",
                "description": "A member: a project-scoped subscriber. Every payment is made on behalf of one, and every access grant resolves to one.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The member's id within the project; the same person in another project is another member.",
                        "examples": [
                            "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the member belongs to.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "username": {
                        "type": "string",
                        "description": "The member's handle on the connector they joined through, when the platform has one.",
                        "examples": [
                            "@janedoe"
                        ]
                    },
                    "first_name": {
                        "type": "string",
                        "description": "The member's first name as the connector reported it.",
                        "examples": [
                            "Jane"
                        ]
                    },
                    "last_name": {
                        "type": "string",
                        "description": "The member's last name as the connector reported it; null when the platform gave none.",
                        "examples": [
                            "Doe"
                        ]
                    },
                    "email": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The address the member chose and verified themselves, their portal sign-in credential; null for most members, who join through a bot and are never asked. Present only for a token holding `project-user:view`; a roster-only token never sees the key.",
                        "examples": [
                            null
                        ]
                    },
                    "billing_email": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Whatever address the member gave a payment provider at checkout, captured automatically on every new payment. Never verified and never used for authentication: treat it as identification only. Null for members who last paid before the capture existed or who joined by access code. Present only for a token holding `project-user:view`.",
                        "examples": [
                            "jane@example.com"
                        ]
                    },
                    "identities": {
                        "type": "array",
                        "description": "The member's connected connector accounts, embedded on the detail read and on a list narrowed with `identity`; absent elsewhere.",
                        "items": {
                            "$ref": "#/components/schemas/MemberIdentityResource"
                        }
                    },
                    "source": {
                        "type": [
                            "array",
                            "null"
                        ],
                        "description": "Where the member came from: the Smart Link credited with them, the door and the campaign tags. Null for a member who arrived with no link and no tags; see the member source object.",
                        "items": {}
                    },
                    "status": {
                        "description": "Where the member stands: `lead` (met the bot, never paid), `trialing`, `customer`, `churned` (no active access) or `banned`.",
                        "anyOf": [
                            {
                                "$ref": "#/components/schemas/ProjectUserStatus"
                            },
                            {
                                "type": "string",
                                "enum": [
                                    "lead",
                                    "trialing",
                                    "customer",
                                    "churned",
                                    "banned"
                                ],
                                "examples": [
                                    "customer"
                                ]
                            }
                        ]
                    },
                    "joined_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the member first joined the project, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the member row was created, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the member row last changed, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "username",
                    "first_name",
                    "last_name",
                    "status",
                    "joined_at",
                    "created_at",
                    "updated_at"
                ],
                "title": "MemberResource"
            },
            "NotificationResource": {
                "type": "object",
                "description": "One entry of the creator's Notifications Center: an alert Subscriby sent them, with where it points and whether they opened it.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The entry's id, the value the mark-read endpoint takes.",
                        "examples": [
                            "0b1f6e2a-7c3d-4e5f-8a9b-0c1d2e3f4a5b"
                        ]
                    },
                    "class": {
                        "type": "string",
                        "description": "The alert class the creator routes on Settings → Notifications: `sales`, `support`, `recovery`, `billing`, `security`, `passes` or `onboarding`.",
                        "enum": [
                            "sales",
                            "support",
                            "recovery",
                            "billing",
                            "security",
                            "passes",
                            "onboarding",
                            "partner",
                            "retention",
                            "copilot"
                        ],
                        "examples": [
                            "support"
                        ]
                    },
                    "class_label": {
                        "type": "string",
                        "description": "The class's name in the creator's language.",
                        "examples": [
                            "Support"
                        ]
                    },
                    "title": {
                        "type": "string",
                        "description": "The alert's heading, the same words the email used, in the creator's language at the time it was sent.",
                        "examples": [
                            "Support backlog in Signals"
                        ]
                    },
                    "body": {
                        "type": "string",
                        "description": "One sentence of context, the email's first line.",
                        "examples": [
                            "Three members are waiting for an answer."
                        ]
                    },
                    "route": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The dashboard screen the entry opens, as a named route, for a client that maps routes to screens; null when the alert points nowhere.",
                        "examples": [
                            "projects.inbox"
                        ]
                    },
                    "params": {
                        "type": "object",
                        "description": "The named route's parameters; null when the alert points nowhere.",
                        "additionalProperties": {
                            "type": "string",
                            "examples": [
                                "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                            ]
                        }
                    },
                    "url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The same place resolved to a URL, for a client that does not map routes; null when the alert points nowhere.",
                        "examples": [
                            "https://app.subscriby.net/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/inbox"
                        ]
                    },
                    "read": {
                        "type": "boolean",
                        "description": "Whether the creator opened the entry.",
                        "examples": [
                            false
                        ]
                    },
                    "read_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it was opened, ISO 8601; null while unread.",
                        "examples": [
                            null
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the alert arrived, ISO 8601.",
                        "examples": [
                            "2026-09-12T10:05:30Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "class",
                    "class_label",
                    "title",
                    "body",
                    "route",
                    "params",
                    "url",
                    "read",
                    "read_at",
                    "created_at"
                ],
                "title": "NotificationResource"
            },
            "OpenRecoveryHandshakeRequest": {
                "type": "object",
                "description": "Which handshake to open.",
                "properties": {
                    "kind": {
                        "description": "`relink` moves the sign-in to a new account and needs the account recovery allowance; `backup` registers a backup account and needs the Growth plan.",
                        "$ref": "#/components/schemas/RecoveryHandshakeKind"
                    }
                },
                "required": [
                    "kind"
                ],
                "title": "OpenRecoveryHandshakeRequest"
            },
            "PartnerPayoutMethod": {
                "type": "string",
                "description": "How a partner takes what the Partner Program owes them. Credit needs nothing typed: an approved commission is applied to the partner's own Stripe balance and offsets their next invoices. The four cash rails are paid by the owner by hand: PayPal and USDT to one typed detail (an email, a wallet address), Wise and Remitly into a bank account (the holder, the bank, its country, the account number, and the codes some transfers need). Either is the partner's money, so it is stored encrypted and never announced. Whatever a rail charges to carry the money comes out of the payout, which the terms say in so many words.\n",
                "enum": [
                    "credit",
                    "paypal",
                    "wise",
                    "remitly",
                    "crypto"
                ],
                "title": "PartnerPayoutMethod"
            },
            "PartnerPayoutResource": {
                "type": "object",
                "description": "A partner payout: cash Subscriby paid the partner, the rail it went by, the transfer's reference and how many commissions it covered.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The payout's id.",
                        "examples": [
                            "0b1c2d3e-4f50-4617-8a9b-0c1d2e3f4a5b"
                        ]
                    },
                    "amount": {
                        "type": "string",
                        "description": "What was paid, as a decimal string with four places.",
                        "examples": [
                            "117.0000"
                        ]
                    },
                    "currency": {
                        "type": "string",
                        "description": "The ISO 4217 code of the amount.",
                        "examples": [
                            "USD"
                        ]
                    },
                    "method": {
                        "type": "string",
                        "description": "The rail the money went by: `paypal`, `wise`, `remitly` or `crypto`.",
                        "enum": [
                            "credit",
                            "paypal",
                            "wise",
                            "remitly",
                            "crypto"
                        ],
                        "examples": [
                            "paypal"
                        ]
                    },
                    "reference": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The transfer's own reference, as Subscriby recorded it; null when none was kept.",
                        "examples": [
                            "PAYPAL-7F3D1C92"
                        ]
                    },
                    "note": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Anything Subscriby noted about the payout; null when nothing was.",
                        "examples": [
                            null
                        ]
                    },
                    "paid_at": {
                        "type": "string",
                        "description": "When the money left, ISO 8601.",
                        "examples": [
                            "2026-11-01T06:30:00+00:00"
                        ]
                    },
                    "rewards_paid": {
                        "type": "integer",
                        "description": "How many commissions the payout covered, oldest first.",
                        "examples": [
                            10
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the row was written, ISO 8601.",
                        "examples": [
                            "2026-11-01T06:30:00+00:00"
                        ]
                    }
                },
                "required": [
                    "id",
                    "amount",
                    "currency",
                    "method",
                    "reference",
                    "note",
                    "paid_at",
                    "rewards_paid",
                    "created_at"
                ],
                "title": "PartnerPayoutResource"
            },
            "PartnerReferralResource": {
                "type": "object",
                "description": "A partner referral: a creator who signed up through the partner's link, code or bot deep link, whether their first paid invoice converted them, and until when the partner earns on them.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The referral's id.",
                        "examples": [
                            "3c4d5e6f-7081-4a2b-9c3d-4e5f6a7b8c9d"
                        ]
                    },
                    "referred_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The referred creator's display name; null when the account is gone. Their email and id are never returned.",
                        "examples": [
                            "Grace Hopper"
                        ]
                    },
                    "source": {
                        "type": "string",
                        "description": "How they arrived: `link` (the web link's cookie), `code_at_signup` (the code typed on the sign-up form) or `bot_deep_link` (a connector's deep link).",
                        "enum": [
                            "link",
                            "code_at_signup",
                            "bot_deep_link"
                        ],
                        "examples": [
                            "link"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "`signed_up` (inside the conversion window, no paid plan yet), `converted` (first Starter or Growth invoice paid, earning), `under_review` (held by Subscriby for a fraud signal), `expired` (the window passed unpaid) or `rejected` (rejected after review).",
                        "enum": [
                            "signed_up",
                            "converted",
                            "under_review",
                            "expired",
                            "rejected"
                        ],
                        "examples": [
                            "converted"
                        ]
                    },
                    "plan": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The platform plan they converted on, `starter` or `growth`; null until converted.",
                        "enum": [
                            "free",
                            "starter",
                            "growth",
                            "custom",
                            null
                        ],
                        "examples": [
                            "starter"
                        ]
                    },
                    "signed_up_at": {
                        "type": "string",
                        "description": "When they signed up, ISO 8601.",
                        "examples": [
                            "2026-10-08T11:00:00+00:00"
                        ]
                    },
                    "expires_at": {
                        "type": "string",
                        "description": "When the conversion window closes unless they pay, ISO 8601.",
                        "examples": [
                            "2027-04-06T11:00:00+00:00"
                        ]
                    },
                    "converted_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When their first paid invoice settled, ISO 8601; null until then.",
                        "examples": [
                            "2026-10-09T14:20:00+00:00"
                        ]
                    },
                    "commission_percent": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The rate locked onto this referral at conversion, as a decimal string with two places; null until converted.",
                        "examples": [
                            "15.00"
                        ]
                    },
                    "commission_ends_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the partner stops earning on this creator, ISO 8601; null until converted.",
                        "examples": [
                            "2027-10-09T14:20:00+00:00"
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the row was written, ISO 8601.",
                        "examples": [
                            "2026-10-08T11:00:00+00:00"
                        ]
                    }
                },
                "required": [
                    "id",
                    "referred_name",
                    "source",
                    "status",
                    "plan",
                    "signed_up_at",
                    "expires_at",
                    "converted_at",
                    "commission_percent",
                    "commission_ends_at",
                    "created_at"
                ],
                "title": "PartnerReferralResource"
            },
            "PartnerReferralStatus": {
                "type": "string",
                "description": "What became of a referred creator's sign-up. `SignedUp` waits for a first paid Starter or Growth invoice inside the conversion window; `Converted` has one and earns for the commission period; `UnderReview` converted on a card that matches the partner's and earns nothing until the owner clears or rejects it; `Expired` ran out of window; `Rejected` was refused after review.\n",
                "enum": [
                    "signed_up",
                    "converted",
                    "under_review",
                    "expired",
                    "rejected"
                ],
                "title": "PartnerReferralStatus"
            },
            "PartnerResource": {
                "type": "object",
                "description": "The caller's standing in the Partner Program: the application's state, the code and the links once approved, the commission ladder, how many creators they referred and converted, what they have earned, and how they are paid; never the payout destination itself.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The partnership's id. A creator holds one.",
                        "examples": [
                            "4b7e2d19-5c3a-4f80-9e6b-1d2c3b4a5f60"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "`applied` (under review by Subscriby), `active` (approved and earning), `rejected` (not approved; `reapply_available_at` says when they may apply again) or `suspended` (approved, but the link no longer attributes and nothing new is earned).",
                        "enum": [
                            "applied",
                            "active",
                            "rejected",
                            "suspended"
                        ],
                        "examples": [
                            "active"
                        ]
                    },
                    "code": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The partner code, seven characters, carried by every link and typeable on the sign-up form; null until approved.",
                        "examples": [
                            "ADA7Q2X"
                        ]
                    },
                    "links": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The addresses to hand out; null until approved.",
                        "properties": {
                            "web": {
                                "type": "string",
                                "description": "The web link: sets the attribution cookie and lands on the marketing site with the friend offer shown.",
                                "examples": [
                                    "https://app.subscriby.net/r/ADA7Q2X"
                                ]
                            },
                            "connectors": {
                                "type": "array",
                                "description": "One deep link per connector whose bot signs creators up, each opening the sign-up conversation with the code attached.",
                                "items": {
                                    "type": "object",
                                    "properties": {
                                        "connector": {
                                            "type": "string",
                                            "description": "The connector key.",
                                            "examples": [
                                                "telegram"
                                            ]
                                        },
                                        "name": {
                                            "type": "string",
                                            "description": "The connector's name, for a label.",
                                            "examples": [
                                                "Telegram"
                                            ]
                                        },
                                        "url": {
                                            "type": "string",
                                            "description": "The deep link.",
                                            "examples": [
                                                "https://t.me/SubscribyBot?start=partner_ADA7Q2X"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "connector",
                                        "name",
                                        "url"
                                    ]
                                }
                            }
                        },
                        "required": [
                            "web",
                            "connectors"
                        ]
                    },
                    "commission_percent": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The rate the partner earns on every invoice of a creator who converts from now on, as a decimal string with two places: `\"15.00\"`. Null until approved.",
                        "examples": [
                            "15.00"
                        ]
                    },
                    "base_percent": {
                        "type": "integer",
                        "description": "Where every partner starts, whole percent.",
                        "examples": [
                            5
                        ]
                    },
                    "max_percent": {
                        "type": "integer",
                        "description": "The ladder's cap, whole percent.",
                        "examples": [
                            30
                        ]
                    },
                    "commitment_points": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Points the verified commitments add; null until approved.",
                        "examples": [
                            10
                        ]
                    },
                    "volume_points": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Points the volume tiers reached add; null until approved.",
                        "examples": [
                            0
                        ]
                    },
                    "paying_referrals": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "How many referred creators have converted, the figure the volume tiers read; null until approved.",
                        "examples": [
                            3
                        ]
                    },
                    "next_tier_at": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The paying-referral count of the next volume tier; null past the last, or until approved.",
                        "examples": [
                            10
                        ]
                    },
                    "next_tier_points": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "What that tier adds; null past the last, or until approved.",
                        "examples": [
                            5
                        ]
                    },
                    "commission_months": {
                        "type": "integer",
                        "description": "How long a commission runs after each conversion, in months.",
                        "examples": [
                            12
                        ]
                    },
                    "hold_days": {
                        "type": "integer",
                        "description": "Days a commission waits before it is payable, so a refund inside the window can take it back.",
                        "examples": [
                            30
                        ]
                    },
                    "minimum_cash_payout": {
                        "type": "string",
                        "description": "The balance a cash rail reaches before Subscriby pays, in USD, as a whole-number string.",
                        "examples": [
                            "50"
                        ]
                    },
                    "friend_discount_percent": {
                        "type": "integer",
                        "description": "The discount a referred creator gets on their first paid months, whole percent.",
                        "examples": [
                            20
                        ]
                    },
                    "friend_discount_months": {
                        "type": "integer",
                        "description": "How many of their first months the discount covers.",
                        "examples": [
                            3
                        ]
                    },
                    "currency": {
                        "type": "string",
                        "description": "The ISO 4217 code every balance is in. Platform invoices are USD, so it is `USD`.",
                        "examples": [
                            "USD"
                        ]
                    },
                    "clicks": {
                        "type": "integer",
                        "description": "How many visits the web link has brought.",
                        "examples": [
                            412
                        ]
                    },
                    "referrals": {
                        "type": "object",
                        "description": "How many creators the partner brought in, by state.",
                        "properties": {
                            "total": {
                                "type": "integer",
                                "description": "Every referral recorded.",
                                "examples": [
                                    7
                                ]
                            },
                            "signed_up": {
                                "type": "integer",
                                "description": "Signed up, not yet on a paid plan, inside their conversion window.",
                                "examples": [
                                    3
                                ]
                            },
                            "converted": {
                                "type": "integer",
                                "description": "Paid their first Starter or Growth invoice and earning.",
                                "examples": [
                                    3
                                ]
                            },
                            "under_review": {
                                "type": "integer",
                                "description": "Held by Subscriby for a fraud signal; earning nothing until cleared.",
                                "examples": [
                                    0
                                ]
                            },
                            "expired": {
                                "type": "integer",
                                "description": "Never paid inside the window.",
                                "examples": [
                                    1
                                ]
                            },
                            "rejected": {
                                "type": "integer",
                                "description": "Rejected after review.",
                                "examples": [
                                    0
                                ]
                            }
                        },
                        "required": [
                            "total",
                            "signed_up",
                            "converted",
                            "under_review",
                            "expired",
                            "rejected"
                        ]
                    },
                    "balance": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "What the partner has earned, as decimal strings with four places in `currency`; null until approved.",
                        "properties": {
                            "pending": {
                                "type": "string",
                                "description": "Commissions still inside the hold.",
                                "examples": [
                                    "11.7000"
                                ]
                            },
                            "payable": {
                                "type": "string",
                                "description": "Approved and not yet settled, clawbacks netted: what the next credit or payout covers.",
                                "examples": [
                                    "52.6500"
                                ]
                            },
                            "credited": {
                                "type": "string",
                                "description": "Settled as Subscriby Credit on the partner's own invoices.",
                                "examples": [
                                    "0.0000"
                                ]
                            },
                            "paid": {
                                "type": "string",
                                "description": "Paid out in cash.",
                                "examples": [
                                    "117.0000"
                                ]
                            },
                            "earned": {
                                "type": "string",
                                "description": "Everything earned: pending, payable, credited and paid together.",
                                "examples": [
                                    "181.3500"
                                ]
                            }
                        },
                        "required": [
                            "pending",
                            "payable",
                            "credited",
                            "paid",
                            "earned"
                        ]
                    },
                    "payout_method": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The rail the partner chose: `credit` (Subscriby Credit on their own invoices), `paypal`, `wise`, `remitly` or `crypto` (USDT on TRC20); null until chosen.",
                        "enum": [
                            "credit",
                            "paypal",
                            "wise",
                            "remitly",
                            "crypto",
                            null
                        ],
                        "examples": [
                            "paypal"
                        ]
                    },
                    "payout_details_complete": {
                        "type": "boolean",
                        "description": "Whether the rail has everything a payment needs. The destination itself (the PayPal address, the wallet, the bank account) is never returned.",
                        "examples": [
                            true
                        ]
                    },
                    "legal_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The name a payment is made out to, as declared; null until declared.",
                        "examples": [
                            "Ada Lovelace"
                        ]
                    },
                    "tax_country": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The country of tax residence, as an ISO 3166-1 alpha-2 code; null until declared.",
                        "examples": [
                            "GB"
                        ]
                    },
                    "us_person": {
                        "type": [
                            "boolean",
                            "null"
                        ],
                        "description": "Whether the partner declared themselves a US person for tax purposes; null until declared.",
                        "examples": [
                            false
                        ]
                    },
                    "terms_accepted_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the partner last accepted the Partner Program Terms, ISO 8601; null until accepted.",
                        "examples": [
                            "2026-10-02T09:14:02+00:00"
                        ]
                    },
                    "terms_version": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The version of the terms accepted, as a date; null until accepted.",
                        "examples": [
                            "2026-10-10"
                        ]
                    },
                    "commitments": {
                        "type": "array",
                        "description": "The promotion commitments the partner made, in the order promised, each with its proof state.",
                        "items": {}
                    },
                    "applied_at": {
                        "type": "string",
                        "description": "When the application was filed, ISO 8601.",
                        "examples": [
                            "2026-10-01T09:14:02+00:00"
                        ]
                    },
                    "joined_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When Subscriby approved it, ISO 8601; null until then.",
                        "examples": [
                            "2026-10-02T09:14:02+00:00"
                        ]
                    },
                    "rejected_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When Subscriby declined it, ISO 8601; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "rejection_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why it was declined, in Subscriby's words; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "reapply_available_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a declined applicant may apply again, ISO 8601; null when they may now, or were not declined.",
                        "examples": [
                            null
                        ]
                    },
                    "suspended_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the partnership was suspended, ISO 8601; null while it stands.",
                        "examples": [
                            null
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the row was written, ISO 8601.",
                        "examples": [
                            "2026-10-01T09:14:02+00:00"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it last changed, ISO 8601.",
                        "examples": [
                            "2026-10-21T08:00:00+00:00"
                        ]
                    }
                },
                "required": [
                    "id",
                    "status",
                    "code",
                    "links",
                    "commission_percent",
                    "base_percent",
                    "max_percent",
                    "commitment_points",
                    "volume_points",
                    "paying_referrals",
                    "next_tier_at",
                    "next_tier_points",
                    "commission_months",
                    "hold_days",
                    "minimum_cash_payout",
                    "friend_discount_percent",
                    "friend_discount_months",
                    "currency",
                    "clicks",
                    "referrals",
                    "balance",
                    "payout_method",
                    "payout_details_complete",
                    "legal_name",
                    "tax_country",
                    "us_person",
                    "terms_accepted_at",
                    "terms_version",
                    "commitments",
                    "applied_at",
                    "joined_at",
                    "rejected_at",
                    "rejection_reason",
                    "reapply_available_at",
                    "suspended_at",
                    "created_at",
                    "updated_at"
                ],
                "title": "PartnerResource"
            },
            "PartnerRewardResource": {
                "type": "object",
                "description": "A partner commission: the invoice it was priced from, the base and the amount as decimal strings, and its state from held to settled or reversed; a clawback is a negative row.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The reward's id.",
                        "examples": [
                            "8e9f0a1b-2c3d-4e5f-8a9b-0c1d2e3f4a5b"
                        ]
                    },
                    "referral_id": {
                        "type": "string",
                        "description": "The referral it was earned on.",
                        "examples": [
                            "3c4d5e6f-7081-4a2b-9c3d-4e5f6a7b8c9d"
                        ]
                    },
                    "kind": {
                        "type": "string",
                        "description": "`commission` (earned on a paid invoice) or `clawback` (a negative row answering a reversal of money already settled).",
                        "enum": [
                            "commission",
                            "clawback"
                        ],
                        "examples": [
                            "commission"
                        ]
                    },
                    "invoice_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The referred creator's Stripe invoice the commission was priced from; null on a clawback.",
                        "examples": [
                            "in_1QExampleInvoice00"
                        ]
                    },
                    "base_amount": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The invoice's total before tax and after discount, as a decimal string with four places; null on a clawback.",
                        "examples": [
                            "31.2000"
                        ]
                    },
                    "amount": {
                        "type": "string",
                        "description": "The commission as a decimal string with four places; negative on a clawback.",
                        "examples": [
                            "4.6800"
                        ]
                    },
                    "currency": {
                        "type": "string",
                        "description": "The ISO 4217 code of both amounts.",
                        "examples": [
                            "USD"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "`pending` (inside the hold), `approved` (payable), `credited` (applied as Subscriby Credit), `paid` (covered by a cash payout) or `reversed` (taken back before it was settled).",
                        "enum": [
                            "pending",
                            "approved",
                            "credited",
                            "paid",
                            "reversed"
                        ],
                        "examples": [
                            "approved"
                        ]
                    },
                    "hold_until": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the hold ends and the commission becomes payable, ISO 8601.",
                        "examples": [
                            "2026-11-08T14:20:00+00:00"
                        ]
                    },
                    "approved_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it became payable, ISO 8601; null until then.",
                        "examples": [
                            "2026-11-08T15:00:00+00:00"
                        ]
                    },
                    "credited_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it was applied as Subscriby Credit, ISO 8601; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "paid_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a cash payout covered it, ISO 8601; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "reversed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it was reversed, ISO 8601; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "payout_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The payout that covered it; null until then.",
                        "examples": [
                            null
                        ]
                    },
                    "reverses_reward_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "On a clawback, the reward whose settled money it takes back; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "note": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why the row was reversed or re-priced: `refund`, `dispute`, `rejected` (the referral was rejected after review) or `repriced` (a commitment lapsed); null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the row was written, ISO 8601.",
                        "examples": [
                            "2026-10-09T14:20:00+00:00"
                        ]
                    }
                },
                "required": [
                    "id",
                    "referral_id",
                    "kind",
                    "invoice_id",
                    "base_amount",
                    "amount",
                    "currency",
                    "status",
                    "hold_until",
                    "approved_at",
                    "credited_at",
                    "paid_at",
                    "reversed_at",
                    "payout_id",
                    "reverses_reward_id",
                    "note",
                    "created_at"
                ],
                "title": "PartnerRewardResource"
            },
            "PartnerRewardStatus": {
                "type": "string",
                "description": "Where a partner commission stands. A commission is born `Pending` behind the hold, becomes `Approved` (payable) when the hold passes, and is settled either as `Credited` on the partner's Stripe balance or `Paid` by a recorded payout; a refund inside the hold makes it `Reversed`, and a refund after settlement leaves it as it is and writes a clawback beside it.\n",
                "enum": [
                    "pending",
                    "approved",
                    "credited",
                    "paid",
                    "reversed"
                ],
                "title": "PartnerRewardStatus"
            },
            "PassRecurrence": {
                "type": "string",
                "enum": [
                    "daily",
                    "weekly",
                    "monthly"
                ],
                "title": "PassRecurrence"
            },
            "PassSalesCutoffAnchor": {
                "type": "string",
                "description": "Which end of an access window the sales cutoff counts back from. This is more than a refinement of the cutoff number: it is the switch that decides whether a window can be bought once it has already opened. Anchoring to the start closes sales before anyone is let in, which is the only behaviour the product had. Anchoring to the end keeps the window on sale while it runs, so someone who notices a live session at 2 PM can buy in and be admitted straight away — with access still ending when that window closes, not later.  A null column means the first-start anchor, so no plan authored before the anchor existed changes behaviour.  Declaration order is the order every picker offers them in, because the two selects render `forSeries()` and `forPass()` directly. They therefore run from the earliest deadline to the latest — before it opens, before the first date ends, before the last one does — and a case declared out of that order shows up jumbled on screen while every test still passes.  The case NAMES say first or last; the backing values do not. `before_start` and `before_end` predate the middle anchor, and they are written into rows on two tables, into a CHECK constraint, into the REST and MCP contracts and into published Zapier and n8n integrations. Renaming the values would break every one of those for a cosmetic gain, so only the PHP names were corrected.\n| |\n|---|\n| `before_start` <br/> Sales close a set number of minutes before the window opens. Nothing is sold once it has started. |\n| `before_first_end` <br/> Series only. Sales stay open into the opening session and close a set number of minutes before that FIRST date ends. The middle ground between the other two, and the one a season ticket actually wants: latecomers can still join on opening night, but once the first session is over the season is closed rather than being sold to someone who has already missed part of what they are paying for.  Meaningless for a single window, where \"before the first date ends\" is simply {@see self::BeforeLastEnd} — which is why {@see self::forPass()} withholds it rather than the pickers filtering by hand. |\n| `before_last_start` <br/> Series only. Sales close a set number of minutes before the LAST date opens, so the season is buyable until its closing session begins. The widest anchor that still guarantees a buyer a whole session. Where {@see self::BeforeLastEnd} can sell a season with minutes of it left, this one stops while there is a complete date still to come — the difference between selling the remainder and selling the fag end of it.  Meaningless for a single window, where the only date is both first and last, so this collapses into {@see self::BeforeFirstStart}. |\n| `before_end` <br/> Sales stay open through the window and close a set number of minutes before it ends. |",
                "enum": [
                    "before_start",
                    "before_first_end",
                    "before_last_start",
                    "before_end"
                ],
                "title": "PassSalesCutoffAnchor"
            },
            "PassScheduleMode": {
                "type": "string",
                "enum": [
                    "fixed",
                    "repeating"
                ],
                "title": "PassScheduleMode"
            },
            "PassWindowResource": {
                "type": "object",
                "description": "A pass window: one dated stretch of access on a time-limited pass plan, generated from the plan's slots or placed by hand.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The window's id, what a pass series points at.",
                        "examples": [
                            "3d5a8c72-b016-4e94-8fa7-61c209d4e738"
                        ]
                    },
                    "plan_id": {
                        "type": "string",
                        "description": "The pass plan the window belongs to.",
                        "examples": [
                            "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b"
                        ]
                    },
                    "plan_name": {
                        "type": "string",
                        "description": "That plan's name, so a list reads without a plan lookup.",
                        "examples": [
                            "Match Day Pass"
                        ]
                    },
                    "starts_at": {
                        "type": "string",
                        "description": "When access opens, ISO 8601 in UTC. Store and compare this.",
                        "examples": [
                            "2026-09-20T13:00:00+00:00"
                        ]
                    },
                    "ends_at": {
                        "type": "string",
                        "description": "When access closes, ISO 8601 in UTC.",
                        "examples": [
                            "2026-09-20T16:00:00+00:00"
                        ]
                    },
                    "timezone": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The IANA zone the plan's schedule was authored in. Render window times in this, never in UTC.",
                        "examples": [
                            "America/New_York"
                        ]
                    },
                    "local_range": {
                        "type": "string",
                        "description": "The same window as a person reads it, already in `timezone`; what the dashboard, the portal and the bot all print.",
                        "examples": [
                            "Sun 20 Sep 2026, 09:00 – 12:00 EDT"
                        ]
                    },
                    "duration_minutes": {
                        "type": "integer",
                        "description": "The length in minutes, derived from the two instants.",
                        "examples": [
                            180
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "`scheduled`, `open`, `closed` or `canceled`. Set by the scheduler as the window's start and end pass; `canceled` only by an explicit cancel.",
                        "enum": [
                            "scheduled",
                            "open",
                            "closed",
                            "canceled"
                        ],
                        "examples": [
                            "scheduled"
                        ]
                    },
                    "source": {
                        "type": "string",
                        "description": "`generated` from the plan's slots, or `manual` when placed by hand. Manual windows survive a schedule rebuild; generated ones are regenerated.",
                        "enum": [
                            "generated",
                            "manual"
                        ],
                        "examples": [
                            "generated"
                        ]
                    },
                    "sellable": {
                        "type": "boolean",
                        "description": "Whether a buyer could purchase this window right now: the plan's sales cutoff, resolved for the whole page in one query rather than per row.",
                        "examples": [
                            true
                        ]
                    },
                    "holders": {
                        "type": "integer",
                        "description": "How many purchases currently hold the window.",
                        "examples": [
                            38
                        ]
                    }
                },
                "required": [
                    "id",
                    "plan_id",
                    "plan_name",
                    "starts_at",
                    "ends_at",
                    "timezone",
                    "local_range",
                    "duration_minutes",
                    "status",
                    "source",
                    "sellable",
                    "holders"
                ],
                "title": "PassWindowResource"
            },
            "PassWindowStatus": {
                "type": "string",
                "enum": [
                    "scheduled",
                    "open",
                    "closed",
                    "canceled"
                ],
                "title": "PassWindowStatus"
            },
            "PaymentMethodResource": {
                "type": "object",
                "description": "A payment method configured on a project: which provider, in which mode, and whether it is linked and on offer. Credentials never appear.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The payment method's id.",
                        "examples": [
                            "a15d70c8-3e46-4b92-b70f-58c9d2140e63"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the method is configured on.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "provider": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The stored provider key: a gateway slug (`stripe`, `paypal`, `razorpay`, `paystack`, `ceypay`, `skrill`, `coinpayments`, `accesscode`) or a `connector:provider` key for a currency a connector brings, as the connector directory lists it. A project carries one method per provider key and mode.",
                        "examples": [
                            "stripe"
                        ]
                    },
                    "connector": {
                        "type": "string",
                        "description": "The connector behind a native payment method: the key before the colon of its `connector:provider` row; null for every gateway and for access codes.",
                        "examples": [
                            null
                        ]
                    },
                    "mode": {
                        "type": "string",
                        "description": "`test` or `live`. Drives which set of provider credentials is used.",
                        "enum": [
                            "live",
                            "test"
                        ],
                        "examples": [
                            "live"
                        ]
                    },
                    "linked": {
                        "type": "boolean",
                        "description": "True once the provider handshake (OAuth callback, API-key verify, Connect onboarding) has completed successfully.",
                        "examples": [
                            true
                        ]
                    },
                    "active": {
                        "type": "boolean",
                        "description": "The creator's switch. A linked-but-inactive method is not offered at checkout and cannot be used to charge subscribers.",
                        "examples": [
                            true
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the method was configured, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the method last changed, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "provider",
                    "connector",
                    "mode",
                    "linked",
                    "active",
                    "created_at",
                    "updated_at"
                ],
                "title": "PaymentMethodResource"
            },
            "PlanKind": {
                "type": "string",
                "description": "What a purchase of a creator's plan actually buys. Plan shape had no discriminator before this. It was inferred from `pass_enabled` plus `recurring` plus `billing_cycle`, which is why a third shape kept falling through filters written as `where('pass_enabled', false)`: a boolean cannot express three things, so every query site had to remember which combination it meant and one of them always forgot.  A `match` over this enum with no `default` is exhaustive, so a fourth shape later fails loudly at every site that has to care rather than silently taking whichever branch happened to be last.\n| |\n|---|\n| `subscription` <br/> Access starts at payment and runs on a billing cycle. |\n| `pass` <br/> One purchase buys one of the plan's own scheduled access windows. |\n| `pass_series` <br/> One purchase buys a curated slate of *other* plans' access windows. |",
                "enum": [
                    "subscription",
                    "pass",
                    "pass_series"
                ],
                "title": "PlanKind"
            },
            "PlanResource": {
                "type": "object",
                "description": "A plan: what one purchase buys. `kind` names exactly one of `billing`, `pass` or `pass_series`; the other two are absent, not null.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The plan's id.",
                        "examples": [
                            "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the plan belongs to.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "kind": {
                        "type": "string",
                        "description": "`subscription`, `pass` or `pass_series`. Names the one block that accompanies it; the other two are absent, not null.",
                        "enum": [
                            "subscription",
                            "pass",
                            "pass_series"
                        ],
                        "examples": [
                            "subscription"
                        ]
                    },
                    "name": {
                        "type": "string",
                        "description": "The name buyers see, unique within the project without regard to case or surrounding spaces.",
                        "examples": [
                            "Premium Monthly"
                        ]
                    },
                    "description": {
                        "description": "The pitch under the name, HTML filtered to a safe subset; null when none was written.",
                        "anyOf": [
                            {
                                "type": "string",
                                "examples": [
                                    "Unlimited access to the research channel."
                                ]
                            },
                            {
                                "type": "array"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "price": {
                        "type": "string",
                        "description": "What one purchase costs, as a decimal string in `currency`. On a pass that buys one window; on a series it buys the whole slate, once. `\"0.00\"` is a free plan.",
                        "examples": [
                            "29.00"
                        ]
                    },
                    "currency": {
                        "type": "object",
                        "description": "The currency the price is charged in.",
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The currency's id, the value `currency_id` takes on a write.",
                                "examples": [
                                    "8f27a0d4-63be-4915-8c07-1a5d9e34b628"
                                ]
                            },
                            "iso": {
                                "type": "string",
                                "description": "The ISO 4217 code, such as `USD`.",
                                "examples": [
                                    "USD"
                                ]
                            },
                            "symbol": {
                                "type": "string",
                                "description": "The symbol to print before the amount.",
                                "examples": [
                                    "$"
                                ]
                            }
                        },
                        "required": [
                            "id",
                            "iso",
                            "symbol"
                        ]
                    },
                    "active": {
                        "type": "boolean",
                        "description": "Whether the plan is on sale. Flip it with the publish and unpublish endpoints, not with an update.",
                        "examples": [
                            true
                        ]
                    },
                    "sales_cap": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "How many purchases the plan takes before pausing itself; null for no limit.",
                        "examples": [
                            10
                        ]
                    },
                    "sales_cap_sold": {
                        "type": "integer",
                        "description": "Purchases counted against the cap since it was last changed or the plan was last published.",
                        "examples": [
                            3
                        ]
                    },
                    "position": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The plan's pinned place in the storefront order; null while it follows the built-in order (passes, then seasons, then subscriptions, cheapest first).",
                        "examples": [
                            0
                        ]
                    },
                    "paused": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Why the plan took itself off sale; null while it is not paused.",
                        "examples": [
                            null
                        ],
                        "properties": {
                            "reason": {
                                "type": "string",
                                "description": "`sales_cap_reached` when the cap filled, `seat_cap_reached` when a season filled its last seat.",
                                "enum": [
                                    "sales_cap_reached",
                                    "seat_cap_reached"
                                ]
                            },
                            "at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "When it paused, ISO 8601."
                            }
                        },
                        "required": [
                            "reason",
                            "at"
                        ]
                    },
                    "cadence": {
                        "type": "string",
                        "description": "The duration in words the portal and the bot print, such as `Per Month`, `Per 3 Hours` or `For all 10 passes`. Use it rather than deriving one from the cycle fields.",
                        "examples": [
                            "Per Month"
                        ]
                    },
                    "eligibility": {
                        "type": "object",
                        "description": "Who may buy. The first three are mutually exclusive.",
                        "properties": {
                            "newcomers_only": {
                                "type": "boolean",
                                "description": "Only members who never held a subscription on the project.",
                                "examples": [
                                    false
                                ]
                            },
                            "customers_only": {
                                "type": "boolean",
                                "description": "Only members who currently hold one.",
                                "examples": [
                                    false
                                ]
                            },
                            "churned_only": {
                                "type": "boolean",
                                "description": "Only members who held one and let it lapse.",
                                "examples": [
                                    false
                                ]
                            },
                            "single_use": {
                                "type": "boolean",
                                "description": "Each member may buy the plan once.",
                                "examples": [
                                    false
                                ]
                            },
                            "access_codes_only": {
                                "type": "boolean",
                                "description": "The plan cannot be bought; it is granted by redeeming an access code.",
                                "examples": [
                                    false
                                ]
                            }
                        },
                        "required": [
                            "newcomers_only",
                            "customers_only",
                            "churned_only",
                            "single_use",
                            "access_codes_only"
                        ]
                    },
                    "resources": {
                        "type": "array",
                        "description": "The places the plan grants, present when the endpoint loaded them. On a series these are the lounge, open for the whole span, not the thing being sold.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "string",
                                    "description": "The resource's id.",
                                    "examples": [
                                        "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6"
                                    ]
                                },
                                "name": {
                                    "type": "string",
                                    "description": "The resource's title.",
                                    "examples": [
                                        "Research channel"
                                    ]
                                },
                                "kind": {
                                    "type": "string",
                                    "description": "`manual` for a perk the creator hands over themselves, or `<connector>:<kind>` for a place a connector hosts.",
                                    "examples": [
                                        "telegram:supergroup"
                                    ]
                                },
                                "connector": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The connector that hosts the place; null for a manual resource.",
                                    "examples": [
                                        "telegram"
                                    ]
                                }
                            },
                            "required": [
                                "id",
                                "name",
                                "kind",
                                "connector"
                            ]
                        }
                    },
                    "billing": {
                        "type": "object",
                        "description": "Cycle, trial and renewal. Present only on `kind: subscription`.",
                        "properties": {
                            "billing_cycle": {
                                "description": "`day`, `week`, `month`, `year` or `lifetime`.",
                                "anyOf": [
                                    {
                                        "$ref": "#/components/schemas/SubscriptionBillingCycle"
                                    },
                                    {
                                        "type": "string",
                                        "enum": [
                                            "day",
                                            "week",
                                            "month",
                                            "year",
                                            "lifetime"
                                        ],
                                        "examples": [
                                            "month"
                                        ]
                                    }
                                ]
                            },
                            "billing_cycle_count": {
                                "type": "integer",
                                "description": "How many cycles one period spans, 1 to 99; always 1 when the cycle is `lifetime`.",
                                "examples": [
                                    1
                                ]
                            },
                            "recurring": {
                                "type": "boolean",
                                "description": "Whether the subscription renews itself. Never true for a crypto or platform currency.",
                                "examples": [
                                    true
                                ]
                            },
                            "disabled_renewal": {
                                "type": "boolean",
                                "description": "Charges once, then lapses at the end of the period instead of renewing.",
                                "examples": [
                                    false
                                ]
                            },
                            "trial_days": {
                                "type": "integer",
                                "description": "Free days before the first charge, 0 to 365.",
                                "examples": [
                                    7
                                ]
                            },
                            "trial_cardless": {
                                "type": "boolean",
                                "description": "Whether the trial starts without a payment method on file.",
                                "examples": [
                                    false
                                ]
                            },
                            "trial_type": {
                                "description": "Whose trial rule applies: `project` for the project's trial settings, `plan` for this plan's own.",
                                "anyOf": [
                                    {
                                        "$ref": "#/components/schemas/TrialModeType"
                                    },
                                    {
                                        "type": "string",
                                        "enum": [
                                            "project",
                                            "plan"
                                        ],
                                        "examples": [
                                            "plan"
                                        ]
                                    }
                                ]
                            }
                        },
                        "required": [
                            "billing_cycle",
                            "billing_cycle_count",
                            "recurring",
                            "disabled_renewal",
                            "trial_days",
                            "trial_cardless",
                            "trial_type"
                        ]
                    },
                    "pass": {
                        "type": "object",
                        "description": "The plan's own dated schedule. Present only on `kind: pass`.",
                        "properties": {
                            "timezone": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The IANA zone the schedule was authored in. Render window times in it, never in UTC.",
                                "examples": [
                                    "America/New_York"
                                ]
                            },
                            "schedule_mode": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "`repeating` for windows generated from `slots`, `fixed` for explicitly dated windows.",
                                "enum": [
                                    "fixed",
                                    "repeating",
                                    null
                                ],
                                "examples": [
                                    "repeating"
                                ]
                            },
                            "recurrence": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "`daily`, `weekly` or `monthly`; null in `fixed` mode.",
                                "enum": [
                                    "daily",
                                    "weekly",
                                    "monthly",
                                    null
                                ],
                                "examples": [
                                    "weekly"
                                ]
                            },
                            "recurrence_ends_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "When window generation stops, ISO 8601; null for no end.",
                                "examples": [
                                    null
                                ]
                            },
                            "sales_cutoff_minutes": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "Sales stop this many minutes before the moment `sales_cutoff_anchor` names; null to sell until the window begins.",
                                "examples": [
                                    60
                                ]
                            },
                            "sales_cutoff_anchor": {
                                "type": "string",
                                "description": "`before_start` or `before_end`. Never null: a plan that never set one reads as `before_start`.",
                                "enum": [
                                    "before_start",
                                    "before_first_end",
                                    "before_last_start",
                                    "before_end"
                                ],
                                "examples": [
                                    "before_start"
                                ]
                            },
                            "slots": {
                                "type": "array",
                                "description": "The repeating schedule, present when the endpoint loaded it. Each slot carries its own length, so one plan can mix a 3-hour and a 14-hour window.",
                                "items": {
                                    "type": "object",
                                    "properties": {
                                        "weekday": {
                                            "type": [
                                                "integer",
                                                "null"
                                            ],
                                            "description": "Day of the week, 0 (Sunday) to 6, on a weekly recurrence; null otherwise.",
                                            "examples": [
                                                0
                                            ]
                                        },
                                        "day_of_month": {
                                            "type": [
                                                "integer",
                                                "null"
                                            ],
                                            "description": "Day of the month, 1 to 31, on a monthly recurrence; null otherwise. 29 to 31 skip the months that lack the day.",
                                            "examples": [
                                                null
                                            ]
                                        },
                                        "start_time": {
                                            "type": "string",
                                            "description": "Local wall-clock start in `timezone`, `HH:MM`.",
                                            "examples": [
                                                "09:00"
                                            ]
                                        },
                                        "duration_minutes": {
                                            "type": "integer",
                                            "description": "How long the window stays open.",
                                            "examples": [
                                                840
                                            ]
                                        }
                                    },
                                    "required": [
                                        "weekday",
                                        "day_of_month",
                                        "start_time",
                                        "duration_minutes"
                                    ]
                                }
                            },
                            "upcoming_windows": {
                                "type": "array",
                                "description": "The next windows, present only where the endpoint loaded them. Timestamps are UTC.",
                                "items": {
                                    "type": "object",
                                    "properties": {
                                        "id": {
                                            "type": "string",
                                            "description": "The window's id, the value a series names in `pass_series.window_ids`.",
                                            "examples": [
                                                "3d5a8c72-b016-4e94-8fa7-61c209d4e738"
                                            ]
                                        },
                                        "starts_at": {
                                            "type": "string",
                                            "description": "When the window opens, UTC.",
                                            "examples": [
                                                "2026-09-20T13:00:00Z"
                                            ]
                                        },
                                        "ends_at": {
                                            "type": "string",
                                            "description": "When it closes, UTC.",
                                            "examples": [
                                                "2026-09-21T03:00:00Z"
                                            ]
                                        },
                                        "status": {
                                            "type": "string",
                                            "description": "`scheduled`, `open`, `closed` or `canceled`.",
                                            "enum": [
                                                "scheduled",
                                                "open",
                                                "closed",
                                                "canceled"
                                            ],
                                            "examples": [
                                                "scheduled"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "id",
                                        "starts_at",
                                        "ends_at",
                                        "status"
                                    ]
                                }
                            }
                        },
                        "required": [
                            "timezone",
                            "schedule_mode",
                            "recurrence",
                            "recurrence_ends_at",
                            "sales_cutoff_minutes",
                            "sales_cutoff_anchor"
                        ]
                    },
                    "pass_series": {
                        "description": "The season ticket's slate, the rules that grow it and its seats. Present only on `kind: pass_series`.",
                        "anyOf": [
                            {
                                "type": "object",
                                "properties": {
                                    "timezone": {
                                        "type": "string",
                                        "description": "Borrowed from the source plans; a series has no zone of its own. Null while the slate is empty.",
                                        "examples": [
                                            "America/New_York"
                                        ]
                                    },
                                    "prevent_overlaps": {
                                        "type": "boolean",
                                        "description": "Whether a window clashing with one already on the slate is refused.",
                                        "examples": [
                                            true
                                        ]
                                    },
                                    "sales_cutoff_minutes": {
                                        "type": "integer",
                                        "description": "Sales stop this many minutes before the moment `sales_cutoff_anchor` names, measured against the whole season.",
                                        "examples": [
                                            0
                                        ]
                                    },
                                    "sales_cutoff_anchor": {
                                        "type": "string",
                                        "description": "Earliest deadline first: `before_start` closes before the first window opens, `before_first_end` during that opening window, `before_last_start` as the last window opens, `before_end` as it ends.",
                                        "enum": [
                                            "before_start",
                                            "before_first_end",
                                            "before_last_start",
                                            "before_end"
                                        ],
                                        "examples": [
                                            "before_start"
                                        ]
                                    },
                                    "seat_cap": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ],
                                        "description": "How many holders may hold the season at once; null for unlimited.",
                                        "examples": [
                                            50
                                        ]
                                    },
                                    "seats_taken": {
                                        "type": "integer",
                                        "description": "Holders currently counted against the cap.",
                                        "examples": [
                                            37
                                        ]
                                    },
                                    "seats_remaining": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ],
                                        "description": "Seats still open; null when uncapped.",
                                        "examples": [
                                            13
                                        ]
                                    },
                                    "starts_at": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "description": "The first window's start, UTC; null while the slate is empty.",
                                        "examples": [
                                            "2026-09-20T13:00:00Z"
                                        ]
                                    },
                                    "ends_at": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "description": "The last window's end, UTC; null while the slate is empty.",
                                        "examples": [
                                            "2026-11-29T22:00:00Z"
                                        ]
                                    },
                                    "window_count": {
                                        "type": "integer",
                                        "description": "How many windows the slate holds, at most 120.",
                                        "examples": [
                                            10
                                        ]
                                    },
                                    "successor_plan_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "description": "The next season, offered to holders first when this one finishes; null when none is set.",
                                        "examples": [
                                            null
                                        ]
                                    },
                                    "presale_hours": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ],
                                        "description": "How long that offer is held for holders only, 1 to 8760; null when none is set.",
                                        "examples": [
                                            48
                                        ]
                                    },
                                    "windows": {
                                        "type": "array",
                                        "description": "The slate. Each entry names the plan the window belongs to, because a series can mix several.",
                                        "items": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "The window's id.",
                                                    "examples": [
                                                        "3d5a8c72-b016-4e94-8fa7-61c209d4e738"
                                                    ]
                                                },
                                                "plan_id": {
                                                    "type": "string",
                                                    "description": "The pass plan the window belongs to.",
                                                    "examples": [
                                                        "0b8e6a2f-4c1d-4e3a-9f52-7d6c1b2a3e45"
                                                    ]
                                                },
                                                "plan_name": {
                                                    "type": "string",
                                                    "description": "That plan's name.",
                                                    "examples": [
                                                        "Match Day Pass"
                                                    ]
                                                },
                                                "starts_at": {
                                                    "type": "string",
                                                    "description": "When the window opens, UTC.",
                                                    "examples": [
                                                        "2026-09-20T13:00:00Z"
                                                    ]
                                                },
                                                "ends_at": {
                                                    "type": "string",
                                                    "description": "When it closes, UTC.",
                                                    "examples": [
                                                        "2026-09-20T16:00:00Z"
                                                    ]
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "`scheduled`, `open`, `closed` or `canceled`.",
                                                    "enum": [
                                                        "scheduled",
                                                        "open",
                                                        "closed",
                                                        "canceled"
                                                    ],
                                                    "examples": [
                                                        "scheduled"
                                                    ]
                                                },
                                                "added_by_rule": {
                                                    "type": "boolean",
                                                    "description": "True when a rule absorbed it rather than the creator picking it by hand.",
                                                    "examples": [
                                                        false
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "plan_id",
                                                "plan_name",
                                                "starts_at",
                                                "ends_at",
                                                "status",
                                                "added_by_rule"
                                            ]
                                        }
                                    },
                                    "rules": {
                                        "type": "array",
                                        "description": "The rules that keep absorbing matching windows into the slate.",
                                        "items": {
                                            "type": "object",
                                            "properties": {
                                                "source_plan_id": {
                                                    "type": "string",
                                                    "description": "The pass plan the rule draws windows from.",
                                                    "examples": [
                                                        "0b8e6a2f-4c1d-4e3a-9f52-7d6c1b2a3e45"
                                                    ]
                                                },
                                                "kind": {
                                                    "type": "string",
                                                    "description": "`date_range` takes every window between `from_at` and `to_at`; `next_n` takes the next `take` windows.",
                                                    "enum": [
                                                        "date_range",
                                                        "next_n"
                                                    ],
                                                    "examples": [
                                                        "date_range"
                                                    ]
                                                },
                                                "from_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The earliest window start the rule takes, UTC; null for no bound.",
                                                    "examples": [
                                                        "2026-09-01T00:00:00Z"
                                                    ]
                                                },
                                                "to_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The latest window start the rule takes, UTC; null for no bound.",
                                                    "examples": [
                                                        "2026-12-01T00:00:00Z"
                                                    ]
                                                },
                                                "take": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "How many windows a `next_n` rule takes; null on a `date_range` rule.",
                                                    "examples": [
                                                        null
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "source_plan_id",
                                                "kind",
                                                "from_at",
                                                "to_at",
                                                "take"
                                            ]
                                        }
                                    },
                                    "blackout_window_ids": {
                                        "type": "object",
                                        "description": "Windows a rule matches but the creator has permanently excluded.",
                                        "additionalProperties": {}
                                    }
                                },
                                "required": [
                                    "timezone",
                                    "prevent_overlaps",
                                    "sales_cutoff_minutes",
                                    "sales_cutoff_anchor",
                                    "seat_cap",
                                    "seats_taken",
                                    "seats_remaining",
                                    "starts_at",
                                    "ends_at",
                                    "window_count",
                                    "successor_plan_id",
                                    "presale_hours",
                                    "windows",
                                    "rules",
                                    "blackout_window_ids"
                                ]
                            },
                            {
                                "type": "object",
                                "properties": {
                                    "timezone": {
                                        "type": "null",
                                        "description": "Borrowed from the source plans; a series has no zone of its own. Null while the slate is empty."
                                    },
                                    "prevent_overlaps": {
                                        "type": "boolean",
                                        "description": "Whether a window clashing with one already on the slate is refused.",
                                        "examples": [
                                            true
                                        ]
                                    },
                                    "sales_cutoff_minutes": {
                                        "type": "integer",
                                        "description": "Sales stop this many minutes before the moment `sales_cutoff_anchor` names, measured against the whole season.",
                                        "examples": [
                                            0
                                        ]
                                    },
                                    "sales_cutoff_anchor": {
                                        "type": "string",
                                        "description": "Earliest deadline first: `before_start` closes before the first window opens, `before_first_end` during that opening window, `before_last_start` as the last window opens, `before_end` as it ends.",
                                        "const": "before_start",
                                        "examples": [
                                            "before_start"
                                        ]
                                    },
                                    "seat_cap": {
                                        "type": "null",
                                        "description": "How many holders may hold the season at once; null for unlimited."
                                    },
                                    "seats_taken": {
                                        "type": "integer",
                                        "description": "Holders currently counted against the cap.",
                                        "examples": [
                                            37
                                        ]
                                    },
                                    "seats_remaining": {
                                        "type": "null",
                                        "description": "Seats still open; null when uncapped."
                                    },
                                    "starts_at": {
                                        "type": "null",
                                        "description": "The first window's start, UTC; null while the slate is empty."
                                    },
                                    "ends_at": {
                                        "type": "null",
                                        "description": "The last window's end, UTC; null while the slate is empty."
                                    },
                                    "window_count": {
                                        "type": "integer",
                                        "description": "How many windows the slate holds, at most 120.",
                                        "examples": [
                                            10
                                        ]
                                    },
                                    "successor_plan_id": {
                                        "type": "null",
                                        "description": "The next season, offered to holders first when this one finishes; null when none is set.",
                                        "examples": [
                                            null
                                        ]
                                    },
                                    "presale_hours": {
                                        "type": "null",
                                        "description": "How long that offer is held for holders only, 1 to 8760; null when none is set."
                                    },
                                    "windows": {
                                        "type": "array",
                                        "description": "The slate. Each entry names the plan the window belongs to, because a series can mix several.",
                                        "items": {
                                            "type": "string"
                                        },
                                        "minItems": 0,
                                        "maxItems": 0
                                    },
                                    "rules": {
                                        "type": "array",
                                        "description": "The rules that keep absorbing matching windows into the slate.",
                                        "items": {
                                            "type": "string"
                                        },
                                        "minItems": 0,
                                        "maxItems": 0
                                    },
                                    "blackout_window_ids": {
                                        "type": "array",
                                        "description": "Windows a rule matches but the creator has permanently excluded.",
                                        "items": {
                                            "type": "string"
                                        },
                                        "minItems": 0,
                                        "maxItems": 0
                                    }
                                },
                                "required": [
                                    "timezone",
                                    "prevent_overlaps",
                                    "sales_cutoff_minutes",
                                    "sales_cutoff_anchor",
                                    "seat_cap",
                                    "seats_taken",
                                    "seats_remaining",
                                    "starts_at",
                                    "ends_at",
                                    "window_count",
                                    "successor_plan_id",
                                    "presale_hours",
                                    "windows",
                                    "rules",
                                    "blackout_window_ids"
                                ]
                            }
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the plan was created, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it last changed, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "kind",
                    "name",
                    "description",
                    "price",
                    "currency",
                    "active",
                    "sales_cap",
                    "sales_cap_sold",
                    "position",
                    "paused",
                    "cadence",
                    "eligibility",
                    "created_at",
                    "updated_at"
                ],
                "title": "PlanResource"
            },
            "PlatformFeeChannel": {
                "type": "string",
                "description": "How a transaction fee reached Subscriby: taken at source by Stripe Connect, or metered onto the creator's own invoice. The distinction is the one a creator cannot see anywhere else: a fee taken at source never appears on their invoice, while a metered one is a share of the invoice's Transaction Fees line.\n",
                "enum": [
                    "connect_at_source",
                    "metered"
                ],
                "title": "PlatformFeeChannel"
            },
            "PlatformFeeKind": {
                "type": "string",
                "description": "What a line of the Transaction Fees ledger was charged for. Every way Subscriby earns a fee from a creator is one case, so the ledger adds up to the invoice's Transaction Fees line and the application fees taken at source together: the fee on a member's payment, the fee on an access-code redemption past the plan's allotment, the fees a trial waived and billed at its end, the emails sent to members during a recovery, and the cost of collecting fees by invoice.\n",
                "enum": [
                    "payment_fee",
                    "access_code_fee",
                    "trial_usage",
                    "outage_emails",
                    "processing_recovery"
                ],
                "title": "PlatformFeeKind"
            },
            "PortalArrangement": {
                "type": "string",
                "description": "Where the portal's sidebar card sits against the main card. The sidebar on the left is the arrangement every portal had; on the right the two columns swap; stacked puts the sidebar card above the main card, centred and narrow; the hero does the same with the banner at full width and taller, so the page opens on the image.\n",
                "enum": [
                    "sidebar_left",
                    "sidebar_right",
                    "stacked",
                    "hero"
                ],
                "title": "PortalArrangement"
            },
            "PortalButtonFill": {
                "type": "string",
                "description": "How the portal's buttons are filled. The dark fill every portal had reads the palette's heading colour and the surface it sits on, so it stays a dark button on a light palette and a light one on a dark palette; the accent fill reads the accent and the foreground picked for it; the outline keeps the surface and draws the heading colour around and inside the button.\n",
                "enum": [
                    "accent",
                    "dark",
                    "outline"
                ],
                "title": "PortalButtonFill"
            },
            "PortalButtonStyle": {
                "type": "string",
                "description": "The shape of the portal's buttons. The pill is the shape every portal had; the rounded button follows the corner radius the design chose, and the square one is nearly sharp whatever the corners do.\n",
                "enum": [
                    "pill",
                    "rounded",
                    "square"
                ],
                "title": "PortalButtonStyle"
            },
            "PortalColorMode": {
                "type": "string",
                "description": "Which of a preset's two palettes the portal paints with. `System` paints the light palette and switches to the dark one when the visitor's browser asks for a dark scheme, through a media query the layout emits beside the light declarations; the other two paint one palette whatever the visitor prefers. Every preset carries a drawn dark palette, so the dark half is never an inversion of the light one.\n",
                "enum": [
                    "light",
                    "dark",
                    "system"
                ],
                "title": "PortalColorMode"
            },
            "PortalCouponBox": {
                "type": "string",
                "description": "When the checkout offers the coupon box. A box on every checkout invites a buyer to go looking for a code; a box that opens only once a coupon arrived with the visit keeps the price plain for everyone else.\n",
                "enum": [
                    "always",
                    "link"
                ],
                "title": "PortalCouponBox"
            },
            "PortalDensity": {
                "type": "string",
                "description": "How much room a plan card takes. Roomy is the padding every portal had; compact tightens the card and the space between cards, for a portal with many plans or several columns.\n",
                "enum": [
                    "compact",
                    "roomy"
                ],
                "title": "PortalDensity"
            },
            "PortalDesignDocumentResource": {
                "type": "object",
                "description": "One portal design document in the stored shape: every choice of the fourteen sections, as the designer saves it and as PUT takes it back.",
                "properties": {
                    "preset": {
                        "type": "string",
                        "description": "The palette the colours started from: `classic`, `dark`, `midnight`, `paper`, `pastel` or `bold`. Sending it recolours the six colours below from the preset and keeps the colour mode and the grid; send a colour beside it to override that one.",
                        "enum": [
                            "classic",
                            "dark",
                            "midnight",
                            "paper",
                            "pastel",
                            "bold"
                        ],
                        "examples": [
                            "midnight"
                        ]
                    },
                    "color_mode": {
                        "type": "string",
                        "description": "`light` or `dark` paints one palette for everyone; `system` paints the light one and switches to the preset's drawn dark palette when the visitor's browser asks for a dark scheme.",
                        "enum": [
                            "light",
                            "dark",
                            "system"
                        ],
                        "examples": [
                            "light"
                        ]
                    },
                    "accent": {
                        "type": "string",
                        "description": "The accent, on the buttons, the highlights and the chosen plan's ring, as a six-digit lowercase hex such as `#a3e635`. The text drawn on it is picked by luminance.",
                        "examples": [
                            "#22d3ee"
                        ]
                    },
                    "accent_secondary": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The second accent, on the pass-series and pass strips, as a hex colour; `null` paints the preset's own.",
                        "examples": [
                            null
                        ]
                    },
                    "background": {
                        "type": "string",
                        "description": "The page colour behind the cards, as a hex colour.",
                        "examples": [
                            "#0f172a"
                        ]
                    },
                    "grid": {
                        "type": "boolean",
                        "description": "Whether the faint dotted grid is drawn over the page colour.",
                        "examples": [
                            true
                        ]
                    },
                    "surface": {
                        "type": "string",
                        "description": "The cards' colour, as a hex colour.",
                        "examples": [
                            "#1e293b"
                        ]
                    },
                    "text": {
                        "type": "string",
                        "description": "The body text colour, as a hex colour. It must read on the surface and on the background: a pair under a 3:1 contrast ratio is refused.",
                        "examples": [
                            "#cbd5e1"
                        ]
                    },
                    "heading": {
                        "type": "string",
                        "description": "The colour of the project's name and every heading, as a hex colour, under the same contrast rule as `text`.",
                        "examples": [
                            "#f8fafc"
                        ]
                    },
                    "muted": {
                        "type": "string",
                        "description": "The colour of the captions, the labels and the small print, as a hex colour, under the same contrast rule as `text`.",
                        "examples": [
                            "#94a3b8"
                        ]
                    },
                    "tagline": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "One line under the project's name, up to 80 characters, or `null` for none.",
                        "examples": [
                            "Weekly research notes and the members lounge"
                        ]
                    },
                    "social_links": {
                        "type": "array",
                        "description": "Up to 12 links under the card, each `{network, url, label}`: `network` one of {social_networks}; `url` an https address; `label` the name shown for a `custom` link, up to 40 characters, ignored on the others.",
                        "items": {}
                    },
                    "font_display": {
                        "type": "string",
                        "description": "The face of the headings: `asap-condensed`, `inter`, `poppins`, `montserrat`, `space-grotesk`, `bebas-neue`, `oswald`, `dm-serif-display`, `playfair-display`, `lora`, `manrope` or `sora`.",
                        "enum": [
                            "asap-condensed",
                            "inter",
                            "poppins",
                            "montserrat",
                            "space-grotesk",
                            "bebas-neue",
                            "oswald",
                            "dm-serif-display",
                            "playfair-display",
                            "lora",
                            "manrope",
                            "sora"
                        ],
                        "examples": [
                            "space-grotesk"
                        ]
                    },
                    "font_body": {
                        "type": "string",
                        "description": "The face of everything but the headings, from the same twelve as `font_display`.",
                        "enum": [
                            "asap-condensed",
                            "inter",
                            "poppins",
                            "montserrat",
                            "space-grotesk",
                            "bebas-neue",
                            "oswald",
                            "dm-serif-display",
                            "playfair-display",
                            "lora",
                            "manrope",
                            "sora"
                        ],
                        "examples": [
                            "inter"
                        ]
                    },
                    "heading_case": {
                        "type": "string",
                        "description": "`uppercase` or `as_written`, for every heading.",
                        "enum": [
                            "uppercase",
                            "as_written"
                        ],
                        "examples": [
                            "uppercase"
                        ]
                    },
                    "type_scale": {
                        "type": "string",
                        "description": "`compact`, `regular` or `large`: one multiplier on every text size.",
                        "enum": [
                            "compact",
                            "regular",
                            "large"
                        ],
                        "examples": [
                            "regular"
                        ]
                    },
                    "radius": {
                        "type": "string",
                        "description": "`sharp`, `soft` or `round` corners on the cards and the fields.",
                        "enum": [
                            "sharp",
                            "soft",
                            "round"
                        ],
                        "examples": [
                            "round"
                        ]
                    },
                    "button_style": {
                        "type": "string",
                        "description": "`pill`, `rounded` or `square` buttons.",
                        "enum": [
                            "pill",
                            "rounded",
                            "square"
                        ],
                        "examples": [
                            "pill"
                        ]
                    },
                    "button_fill": {
                        "type": "string",
                        "description": "`accent` fills the buttons with the accent, `dark` with the heading colour, `outline` draws them hollow.",
                        "enum": [
                            "accent",
                            "dark",
                            "outline"
                        ],
                        "examples": [
                            "dark"
                        ]
                    },
                    "button_case": {
                        "type": "string",
                        "description": "`uppercase` or `as_written`, for every button label.",
                        "enum": [
                            "uppercase",
                            "as_written"
                        ],
                        "examples": [
                            "uppercase"
                        ]
                    },
                    "shadow": {
                        "type": "string",
                        "description": "`none`, `soft` or `strong` shadows under the cards.",
                        "enum": [
                            "none",
                            "soft",
                            "strong"
                        ],
                        "examples": [
                            "strong"
                        ]
                    },
                    "card_border": {
                        "type": "boolean",
                        "description": "Whether the cards carry a hairline border.",
                        "examples": [
                            false
                        ]
                    },
                    "arrangement": {
                        "type": "string",
                        "description": "`sidebar_left` or `sidebar_right` put the card beside the plans, `stacked` puts it above them, `hero` runs the banner across the top.",
                        "enum": [
                            "sidebar_left",
                            "sidebar_right",
                            "stacked",
                            "hero"
                        ],
                        "examples": [
                            "sidebar_left"
                        ]
                    },
                    "content_width": {
                        "type": "string",
                        "description": "`narrow`, `regular` or `wide`: how wide the page runs.",
                        "enum": [
                            "narrow",
                            "regular",
                            "wide"
                        ],
                        "examples": [
                            "regular"
                        ]
                    },
                    "sticky_sidebar": {
                        "type": "boolean",
                        "description": "Whether the sidebar card stays in view while the plans scroll.",
                        "examples": [
                            true
                        ]
                    },
                    "plan_grid": {
                        "type": "string",
                        "description": "`list`, `two` or `three`: how many plan cards sit side by side.",
                        "enum": [
                            "list",
                            "two",
                            "three"
                        ],
                        "examples": [
                            "list"
                        ]
                    },
                    "plan_density": {
                        "type": "string",
                        "description": "`compact` or `roomy` plan cards.",
                        "enum": [
                            "compact",
                            "roomy"
                        ],
                        "examples": [
                            "roomy"
                        ]
                    },
                    "plans_heading": {
                        "type": "boolean",
                        "description": "Whether the heading over the plans is shown.",
                        "examples": [
                            true
                        ]
                    },
                    "metrics_subscribers": {
                        "type": "boolean",
                        "description": "Whether the member count is shown on the card.",
                        "examples": [
                            true
                        ]
                    },
                    "metrics_followers": {
                        "type": "boolean",
                        "description": "Whether the follower count is shown on the card.",
                        "examples": [
                            true
                        ]
                    },
                    "metrics_threshold": {
                        "type": "integer",
                        "description": "The count a figure must reach before it is shown, 0 to 1,000,000, so a young project never shows a small number.",
                        "examples": [
                            0
                        ]
                    },
                    "plans_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The heading over the plans, up to 60 characters; `null` for the built-in wording.",
                        "examples": [
                            null
                        ]
                    },
                    "plans_subtitle": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The line under that heading, up to 120 characters; `null` for the built-in wording.",
                        "examples": [
                            null
                        ]
                    },
                    "label_login": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The Login button's label, up to 24 characters; `null` for the built-in wording.",
                        "examples": [
                            null
                        ]
                    },
                    "label_share": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The Share button's label, up to 24 characters; `null` for the built-in wording.",
                        "examples": [
                            null
                        ]
                    },
                    "label_subscribe": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The button on every plan card, up to 24 characters; `null` for the built-in wording.",
                        "examples": [
                            null
                        ]
                    },
                    "checkout_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The checkout's heading, up to 60 characters; `null` for the built-in wording.",
                        "examples": [
                            null
                        ]
                    },
                    "checkout_subtitle": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The line under the checkout's heading, up to 120 characters; `null` for the built-in wording.",
                        "examples": [
                            null
                        ]
                    },
                    "checkout_note": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A note under the checkout, up to 240 characters; `null` for none.",
                        "examples": [
                            null
                        ]
                    },
                    "success_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The heading of the thank-you screen, up to 60 characters; `null` for the built-in wording.",
                        "examples": [
                            null
                        ]
                    },
                    "success_message": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The thank-you screen's message, up to 400 characters; `null` for the built-in wording.",
                        "examples": [
                            null
                        ]
                    },
                    "perks_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The heading over the perks, up to 60 characters; `null` for the built-in one.",
                        "examples": [
                            null
                        ]
                    },
                    "perks": {
                        "type": "array",
                        "description": "Up to 12 perks, each a line of up to 120 characters; the block shows only with at least one.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "faq_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The heading over the questions, up to 60 characters; `null` for the built-in one.",
                        "examples": [
                            null
                        ]
                    },
                    "faq": {
                        "type": "array",
                        "description": "Up to 12 questions, each `{question, answer}`, the question up to 160 characters and the answer up to 800, both required.",
                        "items": {}
                    },
                    "about_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The name on the card about the creator, up to 60 characters, or `null`; the card shows when a name or a bio is set.",
                        "examples": [
                            null
                        ]
                    },
                    "about_bio": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The bio on the card about the creator, up to 600 characters, or `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "custom_button_label": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The second button's label, up to 24 characters, sent together with `custom_button_url` or both `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "custom_button_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Where the second button leads, an https or http address up to 255 characters, sent together with `custom_button_label` or both `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "footer_refund_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The refund policy link in the footer, an https or http address, or `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "footer_contact_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The contact link in the footer, an https, http or `mailto:` address, or `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "footer_imprint_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The imprint link in the footer, an https or http address, or `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "footer_line": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A line of small print in the footer, up to 120 characters, or `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "footer_help": {
                        "type": "boolean",
                        "description": "Whether the Help link is shown in the footer.",
                        "examples": [
                            true
                        ]
                    },
                    "announcement_text": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The strip across the top of the page, up to 160 characters, or `null` for no strip.",
                        "examples": [
                            null
                        ]
                    },
                    "announcement_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Where the strip leads, an https or http address, or `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "announcement_starts_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the strip starts showing, ISO 8601 in any zone and stored in UTC, or `null` for at once.",
                        "examples": [
                            null
                        ]
                    },
                    "announcement_ends_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the strip comes down, ISO 8601 and after the start, or `null` for never.",
                        "examples": [
                            null
                        ]
                    },
                    "video_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A YouTube or Vimeo address in any shape the share button gives, stored as the canonical watch address, or `null` for no video.",
                        "examples": [
                            null
                        ]
                    },
                    "gallery_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The heading over the gallery, up to 60 characters; `null` for the built-in one.",
                        "examples": [
                            null
                        ]
                    },
                    "gallery": {
                        "type": "array",
                        "description": "Up to 8 picture addresses, each stored through `POST /v1/projects/{project}/portal-design/images/gallery`.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "testimonials_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The heading over the quotes, up to 60 characters; `null` for the built-in one.",
                        "examples": [
                            null
                        ]
                    },
                    "testimonials": {
                        "type": "array",
                        "description": "Up to 12 quotes from members, each `{quote, name, subtitle, avatar_url}`: the words up to 300 characters and the name up to 60, both required; `subtitle` what they are, up to 60 characters, or `null`; `avatar_url` a photo stored through `POST /v1/projects/{project}/portal-design/images/avatar`, or `null` for the first letter of the name.",
                        "items": {}
                    },
                    "sidebar_items": {
                        "type": "array",
                        "description": "The sidebar card's parts in order, each `{key, shown}` with `key` one of `tagline`, `metrics`, `buttons`, `description`, `social_links`, `footer`, every key exactly once; a part left out is appended, shown.",
                        "items": {}
                    },
                    "content_blocks": {
                        "type": "array",
                        "description": "The blocks under the plans in order, each `{key, shown}` with `key` one of `perks`, `about`, `faq`, `video`, `gallery`, `testimonials`, every key exactly once; a block left out is appended, shown.",
                        "items": {}
                    },
                    "locale_switcher": {
                        "type": "boolean",
                        "description": "Whether the list of languages under the card is shown.",
                        "examples": [
                            true
                        ]
                    },
                    "featured_plan_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The plan that carries the Most popular badge, one of the project's own plan ids, or `null` for none.",
                        "examples": [
                            null
                        ]
                    },
                    "coupon_box": {
                        "type": "string",
                        "description": "`always` shows the coupon box on every checkout; `link` shows it only once a coupon arrived with the visit.",
                        "enum": [
                            "always",
                            "link"
                        ],
                        "examples": [
                            "always"
                        ]
                    },
                    "share_button": {
                        "type": "boolean",
                        "description": "Whether the Share button is shown in the header.",
                        "examples": [
                            true
                        ]
                    },
                    "share_networks": {
                        "type": "array",
                        "description": "Which networks the share sheet offers, kept in the sheet's own order: {share_networks}.",
                        "items": {
                            "examples": [
                                "bluesky"
                            ]
                        }
                    },
                    "login_button": {
                        "type": "boolean",
                        "description": "Whether the Login button is shown in the header.",
                        "examples": [
                            true
                        ]
                    },
                    "social_proof": {
                        "type": "boolean",
                        "description": "Whether a line over the plans says how many members joined in the last seven days; it shows only from three up.",
                        "examples": [
                            false
                        ]
                    },
                    "seats_badges": {
                        "type": "boolean",
                        "description": "Whether a pass series card shows how many seats are left.",
                        "examples": [
                            true
                        ]
                    },
                    "seo_indexable": {
                        "type": "boolean",
                        "description": "Whether search engines may list the portal; `false` adds a noindex directive. A portal the project's own readiness keeps out stays unlisted either way.",
                        "examples": [
                            true
                        ]
                    },
                    "seo_social_card": {
                        "type": "boolean",
                        "description": "Whether a shared link unfurls with a card image; `false` leaves the title and the description alone.",
                        "examples": [
                            true
                        ]
                    },
                    "pixel_meta": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The creator's own Meta Pixel id, 10 to 20 digits, or `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "pixel_ga4": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The creator's own Google Analytics 4 measurement id, `G-` followed by 4 to 15 letters or digits, or `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "pixel_tiktok": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The creator's own TikTok Pixel id, 10 to 30 letters or digits, or `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "pixel_google_ads": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The creator's own Google Ads conversion id, `AW-` followed by 6 to 12 digits, or `null`.",
                        "examples": [
                            null
                        ]
                    },
                    "custom_css": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A stylesheet of up to 16,384 characters printed after the theme so its rules win; refused when it would load, run or escape (`@import`, `url(`, `expression(`, `javascript:`, a closing `style` tag and the like); `null` for none.",
                        "examples": [
                            null
                        ]
                    },
                    "seo_title_suffix": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The words after the project's name in the page title, up to 60 characters, or `null` for the built-in ones.",
                        "examples": [
                            null
                        ]
                    },
                    "seo_description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The description search engines and shared links show, up to 160 characters, or `null` for one cut from the project's text.",
                        "examples": [
                            null
                        ]
                    },
                    "social_card_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A card image of the creator's own, stored through `POST /v1/projects/{project}/portal-design/images/card` and sent in the generated card's place, or `null` for the generated card.",
                        "examples": [
                            null
                        ]
                    },
                    "default_locale": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The language the portal's own address opens in, as a code from `locales`, or `null` for the platform's default.",
                        "enum": [
                            "en",
                            "fr",
                            "es",
                            "it",
                            "hi",
                            "bn",
                            "de",
                            "pt",
                            "tr",
                            "si",
                            null
                        ],
                        "examples": [
                            null
                        ]
                    },
                    "locales": {
                        "type": "array",
                        "description": "The languages the switcher offers, as codes from `en`, `fr`, `es`, `it`, `hi`, `bn`, `de`, `pt`, `tr`, `si`, never empty and always carrying `default_locale`.",
                        "items": {
                            "examples": [
                                "en"
                            ]
                        }
                    }
                },
                "required": [
                    "preset",
                    "color_mode",
                    "accent",
                    "accent_secondary",
                    "background",
                    "grid",
                    "surface",
                    "text",
                    "heading",
                    "muted",
                    "tagline",
                    "social_links",
                    "font_display",
                    "font_body",
                    "heading_case",
                    "type_scale",
                    "radius",
                    "button_style",
                    "button_fill",
                    "button_case",
                    "shadow",
                    "card_border",
                    "arrangement",
                    "content_width",
                    "sticky_sidebar",
                    "plan_grid",
                    "plan_density",
                    "plans_heading",
                    "metrics_subscribers",
                    "metrics_followers",
                    "metrics_threshold",
                    "plans_title",
                    "plans_subtitle",
                    "label_login",
                    "label_share",
                    "label_subscribe",
                    "checkout_title",
                    "checkout_subtitle",
                    "checkout_note",
                    "success_title",
                    "success_message",
                    "perks_title",
                    "perks",
                    "faq_title",
                    "faq",
                    "about_name",
                    "about_bio",
                    "custom_button_label",
                    "custom_button_url",
                    "footer_refund_url",
                    "footer_contact_url",
                    "footer_imprint_url",
                    "footer_line",
                    "footer_help",
                    "announcement_text",
                    "announcement_url",
                    "announcement_starts_at",
                    "announcement_ends_at",
                    "video_url",
                    "gallery_title",
                    "gallery",
                    "testimonials_title",
                    "testimonials",
                    "sidebar_items",
                    "content_blocks",
                    "locale_switcher",
                    "featured_plan_id",
                    "coupon_box",
                    "share_button",
                    "share_networks",
                    "login_button",
                    "social_proof",
                    "seats_badges",
                    "seo_indexable",
                    "seo_social_card",
                    "pixel_meta",
                    "pixel_ga4",
                    "pixel_tiktok",
                    "pixel_google_ads",
                    "custom_css",
                    "seo_title_suffix",
                    "seo_description",
                    "social_card_url",
                    "default_locale",
                    "locales"
                ],
                "title": "PortalDesignDocumentResource"
            },
            "PortalDesignResource": {
                "type": "object",
                "description": "A project's portal design: the document members see, the draft being edited when there is one, when each last moved, and a signed address that previews the draft.",
                "properties": {
                    "project_id": {
                        "type": "string",
                        "description": "The project.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "published": {
                        "description": "The design members see: the defaults until something was published.",
                        "$ref": "#/components/schemas/PortalDesignDocumentResource"
                    },
                    "draft": {
                        "description": "The design being edited, or `null` while nothing is drafted. A `PUT` writes here; `publish` makes it the published design.",
                        "anyOf": [
                            {
                                "$ref": "#/components/schemas/PortalDesignDocumentResource"
                            },
                            {
                                "type": "null",
                                "examples": [
                                    null
                                ]
                            }
                        ]
                    },
                    "has_draft": {
                        "type": "boolean",
                        "description": "Whether a draft waits to be published or discarded.",
                        "examples": [
                            false
                        ]
                    },
                    "draft_updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the draft was last saved, ISO 8601, or `null` without a draft.",
                        "examples": [
                            null
                        ]
                    },
                    "published_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a design was last published, ISO 8601, or `null` while the portal is on the defaults.",
                        "examples": [
                            "2026-10-26T16:40:08+00:00"
                        ]
                    },
                    "preview_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The portal address with a signature that shows the draft for ten minutes from this read, or the published design when nothing is drafted. Null until the project has a handle, because there is no portal page to preview.",
                        "examples": [
                            "https://my.subscriby.net/research-premium?preview=7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13&expires=1793032000&signature=9c1d…"
                        ]
                    }
                },
                "required": [
                    "project_id",
                    "published",
                    "draft",
                    "has_draft",
                    "draft_updated_at",
                    "published_at",
                    "preview_url"
                ],
                "title": "PortalDesignResource"
            },
            "PortalFont": {
                "type": "string",
                "description": "The curated faces a portal may set its display and body type in. Twelve faces, every one an open licence and self-hosted as a latin subset, so a member's browser never calls a font service; the two the portal always had head the list. A face names itself rather than a translated word, as a brand does, and says whether it is a serif so the fallback stack behind it reads the same way while it loads.\n",
                "enum": [
                    "asap-condensed",
                    "inter",
                    "poppins",
                    "montserrat",
                    "space-grotesk",
                    "bebas-neue",
                    "oswald",
                    "dm-serif-display",
                    "playfair-display",
                    "lora",
                    "manrope",
                    "sora"
                ],
                "title": "PortalFont"
            },
            "PortalImageResource": {
                "type": "object",
                "description": "A picture stored for the portal design, cut to its slot, with the address to write into the design.",
                "properties": {
                    "slot": {
                        "type": "string",
                        "description": "`gallery` (cut to 1200 by 800), `avatar` (160 by 160) or `card` (1200 by 630).",
                        "enum": [
                            "gallery",
                            "avatar",
                            "card"
                        ],
                        "examples": [
                            "gallery"
                        ]
                    },
                    "url": {
                        "type": "string",
                        "description": "The stored picture's address, to write into `gallery`, a quote's `avatar_url` or `social_card_url`.",
                        "examples": [
                            "https://static.subscriby.net/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/portal/gallery_1761495608_k3m9qa.jpg"
                        ]
                    },
                    "width": {
                        "type": "integer",
                        "description": "The stored width in pixels.",
                        "enum": [
                            1200,
                            160
                        ],
                        "examples": [
                            1200
                        ]
                    },
                    "height": {
                        "type": "integer",
                        "description": "The stored height in pixels.",
                        "enum": [
                            800,
                            160,
                            630
                        ],
                        "examples": [
                            800
                        ]
                    }
                },
                "required": [
                    "slot",
                    "url",
                    "width",
                    "height"
                ],
                "title": "PortalImageResource"
            },
            "PortalImageSlot": {
                "type": "string",
                "description": "The places a design stores a picture of its own: the gallery, a member's photo beside their words, and the card a shared link unfurls with. Each slot has one size, cut to the centre as the banner and the project photo are, so the page never loads a picture larger than it shows.\n",
                "enum": [
                    "gallery",
                    "avatar",
                    "card"
                ],
                "title": "PortalImageSlot"
            },
            "PortalPlanGrid": {
                "type": "string",
                "description": "How many columns the plan cards fill on a wide screen. The list is the one column every portal had; two and three columns fold back to one on a phone, as the cards were drawn for that width from the start.\n",
                "enum": [
                    "list",
                    "two",
                    "three"
                ],
                "title": "PortalPlanGrid"
            },
            "PortalPreset": {
                "type": "string",
                "description": "The starting palettes a portal design is built from. A preset sets every colour of the design at once and stays editable afterwards; `Classic` is the exact look every portal had before the designer existed, which is why its light palette is the design's default. Each preset carries a light and a dark palette drawn by hand, because an inverted light palette reads as broken on a dark screen: the dark half keeps the accent and re-draws the backgrounds and the text.\n",
                "enum": [
                    "classic",
                    "dark",
                    "midnight",
                    "paper",
                    "pastel",
                    "bold"
                ],
                "title": "PortalPreset"
            },
            "PortalRadius": {
                "type": "string",
                "description": "How rounded the portal's corners are. One choice moves every corner together, the two surface cards and the plan cards included, through the bundle's own radius tokens; the round setting is exactly the look every portal had and emits nothing.\n",
                "enum": [
                    "sharp",
                    "soft",
                    "round"
                ],
                "title": "PortalRadius"
            },
            "PortalShadow": {
                "type": "string",
                "description": "How much the portal's surfaces lift off the page. Three shadows move together: the one under the surface and plan cards, the one under anything that floats (a modal, a menu) and the soft one under small things like the project photo; the strong setting is the depth every portal had.\n",
                "enum": [
                    "none",
                    "soft",
                    "strong"
                ],
                "title": "PortalShadow"
            },
            "PortalTextCase": {
                "type": "string",
                "description": "How the portal's headings set their letters. The portal always shouted its headings in capitals; a serif or a script face reads better as written, so the case is a choice of its own rather than a property of the face.\n",
                "enum": [
                    "uppercase",
                    "as_written"
                ],
                "title": "PortalTextCase"
            },
            "PortalTypeScale": {
                "type": "string",
                "description": "How large the portal sets its type. One factor over every text size the templates use, so the page keeps its proportions; the regular scale is exactly the size every portal had, and emits nothing.\n",
                "enum": [
                    "compact",
                    "regular",
                    "large"
                ],
                "title": "PortalTypeScale"
            },
            "PortalWidth": {
                "type": "string",
                "description": "How wide the portal's column is on a large screen. Regular is the width every portal had; narrow suits a page with little beside the plans, wide a page with several plan columns. The classes that draw each width live in the page template, where the bundle reads them.\n",
                "enum": [
                    "narrow",
                    "regular",
                    "wide"
                ],
                "title": "PortalWidth"
            },
            "ProjectResource": {
                "type": "object",
                "description": "A project: the top-level container for a membership business. Every plan, subscriber, payment method and resource lives under one.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The project's id, the value every project-scoped endpoint takes in its path.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "team_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The team the project belongs to.",
                        "examples": [
                            "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86"
                        ]
                    },
                    "user_id": {
                        "type": "string",
                        "description": "The creator who owns the project.",
                        "examples": [
                            "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                        ]
                    },
                    "name": {
                        "type": "string",
                        "description": "The project's name, 5 to 255 characters.",
                        "examples": [
                            "Research Premium"
                        ]
                    },
                    "handle": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The project's handle: lowercase letters, digits, dashes and underscores, unique across every project's current and former handles, the last segment of the portal URL. Null while the portal page is switched off; every former handle keeps redirecting to the current one.",
                        "examples": [
                            "research-premium"
                        ]
                    },
                    "description": {
                        "description": "What the project offers, up to 1,000 characters of HTML filtered to a safe subset; null when none.",
                        "anyOf": [
                            {
                                "type": "string",
                                "examples": [
                                    "Weekly deep-dive research notes."
                                ]
                            },
                            {
                                "type": "array"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "terms": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The URL of the terms members are asked to accept; null when none.",
                        "examples": [
                            "https://example.com/terms"
                        ]
                    },
                    "privacy": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The URL of the privacy policy members are asked to accept; null when none.",
                        "examples": [
                            "https://example.com/privacy"
                        ]
                    },
                    "banner_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The hosted banner artwork; null until uploaded and processed.",
                        "examples": [
                            "https://static.subscriby.net/projects/7f3d1c92/banner.webp"
                        ]
                    },
                    "photo_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The hosted photo artwork; null until uploaded and processed.",
                        "examples": [
                            "https://static.subscriby.net/projects/7f3d1c92/photo.webp"
                        ]
                    },
                    "storefront_arrangement": {
                        "type": "string",
                        "description": "How the portal, the embed and the bot order the plans on offer: `manual` is the order pinned from **Storefront Order** with the built-in order (passes, seasons, then subscriptions, cheapest first) behind it; `live` puts the passes and seasons whose access is on now first, the one ending soonest at the top, then those opening soonest, then the rest in the pinned order. `live` needs the owner's time-limited passes capability (Growth, or the Passes Addon); the storefronts fall back to `manual` the moment it lapses, and the stored value is reset to `manual` with a `project.updated` event.",
                        "enum": [
                            "manual",
                            "live"
                        ]
                    },
                    "outage_compensations": {
                        "type": "boolean",
                        "description": "The **Outage Compensation** switch: when a platform refuses the project's connector for an hour or more and later answers again, every member whose paid access overlapped the gap gets the lost time added to the end of their access automatically. True on every new project.",
                        "examples": [
                            true
                        ]
                    },
                    "hide_branding": {
                        "type": "boolean",
                        "description": "The **Remove Subscriby Branding** switch: true takes the \"Powered by\" mark off the portal page, its social card and the bot while the owner's tier grants `no_branding`; off by default on every plan."
                    },
                    "active": {
                        "type": "boolean",
                        "description": "Whether the project is live. Archiving flips it to false and keeps everything; restoring flips it back.",
                        "examples": [
                            true
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the project was created, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the project last changed, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "team_id",
                    "user_id",
                    "name",
                    "handle",
                    "description",
                    "terms",
                    "privacy",
                    "banner_url",
                    "photo_url",
                    "storefront_arrangement",
                    "outage_compensations",
                    "hide_branding",
                    "active",
                    "created_at",
                    "updated_at"
                ],
                "title": "ProjectResource"
            },
            "ProjectUserStatus": {
                "type": "string",
                "enum": [
                    "lead",
                    "trialing",
                    "customer",
                    "churned",
                    "banned"
                ],
                "examples": [
                    "customer"
                ],
                "title": "ProjectUserStatus"
            },
            "ReadmissionRollCallResource": {
                "type": "object",
                "description": "Where the re-admission after a channel recovery stands: how many members were given a fresh link, how many have come back, and whether a reminder can go out.",
                "properties": {
                    "total": {
                        "type": "integer",
                        "description": "How many members the swap set out to re-admit.",
                        "examples": [
                            340
                        ]
                    },
                    "regranted": {
                        "type": "integer",
                        "description": "How many hold a fresh link into the new chat.",
                        "examples": [
                            340
                        ]
                    },
                    "failed": {
                        "type": "integer",
                        "description": "How many could not be given one.",
                        "examples": [
                            0
                        ]
                    },
                    "unreachable": {
                        "type": "integer",
                        "description": "How many the bot could not message.",
                        "examples": [
                            12
                        ]
                    },
                    "emailed": {
                        "type": "integer",
                        "description": "How many of the unreachable were told by email instead, at the per-email fee, when the project opted in.",
                        "examples": [
                            12
                        ]
                    },
                    "joined": {
                        "type": "integer",
                        "description": "How many the platform has approved into the new chat; stamped the moment a join request is approved.",
                        "examples": [
                            338
                        ]
                    },
                    "pending": {
                        "type": "integer",
                        "description": "Who is still outside: `regranted` minus `joined`.",
                        "examples": [
                            2
                        ]
                    },
                    "nudged": {
                        "type": "integer",
                        "description": "How many reminders have gone out so far.",
                        "examples": [
                            1
                        ]
                    },
                    "settled": {
                        "type": "boolean",
                        "description": "True once the queue has handled everyone, so the counters will not move on their own.",
                        "examples": [
                            true
                        ]
                    },
                    "cooling_down": {
                        "type": "boolean",
                        "description": "True while the reminder cooldown has not passed since the last nudge.",
                        "examples": [
                            false
                        ]
                    },
                    "can_nudge": {
                        "type": "boolean",
                        "description": "True when somebody is still outside and the cooldown has passed; `cooling_down` and `nudge_available_at` explain a false.",
                        "examples": [
                            true
                        ]
                    },
                    "last_nudged_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the last reminder went out, ISO 8601; null if none has.",
                        "examples": [
                            "2026-09-12T09:00:00Z"
                        ]
                    },
                    "nudge_available_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the next reminder may go out, ISO 8601; null when one may go out now or nobody is waiting.",
                        "examples": [
                            "2026-09-12T10:00:00Z"
                        ]
                    }
                },
                "required": [
                    "total",
                    "regranted",
                    "failed",
                    "unreachable",
                    "emailed",
                    "joined",
                    "pending",
                    "nudged",
                    "settled",
                    "cooling_down",
                    "can_nudge",
                    "last_nudged_at",
                    "nudge_available_at"
                ],
                "title": "ReadmissionRollCallResource"
            },
            "RecoveryAccountResource": {
                "type": "object",
                "description": "Where the creator's own account stands for recovery: the accounts by display name only, whether a backup is kept, and the newest handshake of each kind.",
                "properties": {
                    "primary_display_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The account that signs the creator in, as the connector reported it (display name, else handle, else the platform's id); null when none is linked. Connector identifiers never appear.",
                        "examples": [
                            "Ada"
                        ]
                    },
                    "backup_identity_registered": {
                        "type": "boolean",
                        "description": "Whether a backup account is kept ahead of a ban.",
                        "examples": [
                            true
                        ]
                    },
                    "backup_display_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The backup account as the connector reported it; null when none is kept.",
                        "examples": [
                            "Backup Ada"
                        ]
                    },
                    "relink_handshake": {
                        "type": [
                            "array",
                            "null"
                        ],
                        "description": "The newest handshake that moves the sign-in, in whatever state, so a client can pick up a flow the creator started on the dashboard or in the bot; null when none was ever opened.",
                        "examples": [
                            null
                        ],
                        "items": {}
                    },
                    "backup_handshake": {
                        "type": [
                            "array",
                            "null"
                        ],
                        "description": "The newest handshake that registers a backup, in whatever state; null when none was ever opened.",
                        "items": {}
                    }
                },
                "required": [
                    "primary_display_name",
                    "backup_identity_registered",
                    "backup_display_name",
                    "relink_handshake",
                    "backup_handshake"
                ],
                "title": "RecoveryAccountResource"
            },
            "RecoveryAllowanceResource": {
                "type": "object",
                "description": "How many recoveries of one kind the creator may still run: what the rolling window allows on its own, what support has released on top, and whether the next one would start right now.",
                "properties": {
                    "kind": {
                        "type": "string",
                        "description": "The kind of recovery: `account` (the creator's sign-in account), `bot` (a project's bot) or `resources` (the channels and groups a project sells).",
                        "enum": [
                            "account",
                            "bot",
                            "resources"
                        ],
                        "examples": [
                            "account"
                        ]
                    },
                    "kind_label": {
                        "type": "string",
                        "description": "The kind in the connector's own words, such as \"Project Bot\", in the creator's language.",
                        "examples": [
                            "Telegram Account"
                        ]
                    },
                    "self_service_remaining": {
                        "type": "integer",
                        "description": "What the rolling window still allows on its own.",
                        "examples": [
                            1
                        ]
                    },
                    "grant_remaining": {
                        "type": "integer",
                        "description": "What support has released on top and not yet spent.",
                        "examples": [
                            0
                        ]
                    },
                    "remaining": {
                        "type": "integer",
                        "description": "The sum of the two.",
                        "examples": [
                            1
                        ]
                    },
                    "allowed": {
                        "type": "boolean",
                        "description": "Whether a recovery of that kind would start right now.",
                        "examples": [
                            true
                        ]
                    },
                    "uses_grant": {
                        "type": "boolean",
                        "description": "True when the next recovery would spend a support grant rather than the self-service allowance.",
                        "examples": [
                            false
                        ]
                    },
                    "last_used_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the kind was last recovered inside the window, ISO 8601; null if never.",
                        "examples": [
                            null
                        ]
                    },
                    "next_self_service_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the self-service allowance returns, ISO 8601; null while it is available.",
                        "examples": [
                            null
                        ]
                    }
                },
                "required": [
                    "kind",
                    "kind_label",
                    "self_service_remaining",
                    "grant_remaining",
                    "remaining",
                    "allowed",
                    "uses_grant",
                    "last_used_at",
                    "next_self_service_at"
                ],
                "title": "RecoveryAllowanceResource"
            },
            "RecoveryEmailDelivery": {
                "type": "string",
                "description": "How a project reaches the members its bot cannot message after a swap. A replaced channel re-admits every live member through the project bot, but a member who never started the bot, or whose bot was banned in the same incident, cannot be reached that way. The creator decides once per project whether the platform emails those members on their behalf, at a per-email fee added to the transaction fees, or whether they download the list and write themselves. The default is the free one, so nobody is charged for a choice they did not make.\n",
                "enum": [
                    "platform",
                    "self"
                ],
                "title": "RecoveryEmailDelivery"
            },
            "RecoveryHandshakeKind": {
                "type": "string",
                "description": "What a completed identity handshake is for. The same deep link and the same bot-side verification serve two purposes: replacing the creator's identity after a ban (`Relink`), and registering a second identity ahead of time so a later ban is a one-click switch (`Backup`). The kind is fixed when the handshake opens, so a link minted to register a backup can never be used to replace the primary identity.\n",
                "enum": [
                    "relink",
                    "backup"
                ],
                "title": "RecoveryHandshakeKind"
            },
            "RecoveryHandshakeResource": {
                "type": "object",
                "description": "An identity handshake: the code and link the creator completes from the account to detect, and, once an account has tapped, who that was in neutral terms.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The handshake's id, the value the poll, cancel and confirm endpoints take."
                    },
                    "kind": {
                        "type": "string",
                        "description": "`relink` (move the sign-in to a new account) or `backup` (register a backup account).",
                        "enum": [
                            "relink",
                            "backup"
                        ]
                    },
                    "kind_label": {
                        "type": "string",
                        "description": "The kind in the creator's language.",
                        "enum": [
                            "Replace my connected account",
                            "Register a backup account"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "`pending` until an account taps, `completed` when one has, `expired` when the code ran out or was cancelled, `consumed` once confirmed.",
                        "enum": [
                            "pending",
                            "completed",
                            "consumed",
                            "expired"
                        ]
                    },
                    "status_label": {
                        "type": "string",
                        "description": "The status in the creator's language.",
                        "enum": [
                            "Waiting on the connector",
                            "Account detected",
                            "Linked",
                            "Expired"
                        ]
                    },
                    "code": {
                        "type": "string",
                        "description": "The eight-character code to type into the bot."
                    },
                    "start_link": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The link that opens the bot on the code; null when the creator cannot be reached on the connector."
                    },
                    "connector": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The connector the handshake runs on, by key."
                    },
                    "detected_display_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The account that tapped, as the connector reported it; null while pending."
                    },
                    "detected_identity_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The neutral identity id of the account that tapped, never the connector's own account identifier; null while pending."
                    },
                    "expires_at": {
                        "type": "string",
                        "description": "When the code stops working, fifteen minutes after minting, ISO 8601."
                    },
                    "completed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When an account tapped, ISO 8601; null while pending."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the handshake was opened, ISO 8601."
                    }
                },
                "required": [
                    "id",
                    "kind",
                    "kind_label",
                    "status",
                    "status_label",
                    "code",
                    "start_link",
                    "connector",
                    "detected_display_name",
                    "detected_identity_id",
                    "expires_at",
                    "completed_at",
                    "created_at"
                ],
                "title": "RecoveryHandshakeResource"
            },
            "RecoveryIncidentFilter": {
                "type": "string",
                "description": "Which recovery incidents a list shows. `Open` is what still needs attention, so it is the default: an integration polling the list wants the problems, not the archive. `Resolved` is the record of what healed or was fixed; `All` is both.\n",
                "enum": [
                    "open",
                    "resolved",
                    "all"
                ],
                "title": "RecoveryIncidentFilter"
            },
            "RecoveryIncidentResource": {
                "type": "object",
                "description": "A recovery incident: one problem a health probe detected and has not yet seen fixed.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The incident's id.",
                        "examples": [
                            "6f1e9b27-4c3a-4d58-9e02-b7a1c5d38f64"
                        ]
                    },
                    "kind": {
                        "type": "string",
                        "description": "`account` (the creator's sign-in account unreachable), `bot` (a project's bot refused by the platform) or `resources` (a channel or group the project sells gone or no longer administered).",
                        "enum": [
                            "account",
                            "bot",
                            "resources"
                        ],
                        "examples": [
                            "resources"
                        ]
                    },
                    "kind_label": {
                        "type": "string",
                        "description": "The kind in the connector's own words, in the creator's language.",
                        "examples": [
                            "Channels and Groups"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "`open` while the problem stands, `resolved` once a later probe found the thing healthy or a recovery replaced it.",
                        "enum": [
                            "open",
                            "resolved"
                        ],
                        "examples": [
                            "open"
                        ]
                    },
                    "status_label": {
                        "type": "string",
                        "description": "The status in the creator's language.",
                        "enum": [
                            "Open",
                            "Resolved"
                        ],
                        "examples": [
                            "Open"
                        ]
                    },
                    "connector": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The connector the incident is on, by key; null when it concerns no connector.",
                        "examples": [
                            "telegram"
                        ]
                    },
                    "project_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The project concerned; null on an account incident.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "project_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "That project's name, so an integration can say which project without another call; null on an account incident.",
                        "examples": [
                            "Research Premium"
                        ]
                    },
                    "resource_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The resource concerned; set on `resources` incidents only.",
                        "examples": [
                            "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6"
                        ]
                    },
                    "resource_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "That resource's title; set on `resources` incidents only.",
                        "examples": [
                            "Signals"
                        ]
                    },
                    "reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The connector's own code for what it saw, such as `chat_not_found`, `bot_removed`, `bot_not_administrator`, `bot_missing_rights` or `connector_api_error`; null when the probe recorded no reason, as on account incidents.",
                        "examples": [
                            "chat_not_found"
                        ]
                    },
                    "reason_label": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "That code in the connector's words; null when no reason was recorded.",
                        "examples": [
                            "Channel not found"
                        ]
                    },
                    "reason_explanation": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The connector's explanation of the code, the same sentence the alert email carried, in Markdown; null when no reason was recorded.",
                        "examples": [
                            "**Most likely cause:** the platform deleted or banned the channel. Replace it with a new one."
                        ]
                    },
                    "detected_at": {
                        "type": "string",
                        "description": "When the probe first saw the problem, ISO 8601.",
                        "examples": [
                            "2026-09-12T03:19:04Z"
                        ]
                    },
                    "resolved_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the problem was seen fixed, ISO 8601; null while open.",
                        "examples": [
                            null
                        ]
                    },
                    "resolved_by_operation_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The recovery that fixed it, when one did; null otherwise.",
                        "examples": [
                            null
                        ]
                    }
                },
                "required": [
                    "id",
                    "kind",
                    "kind_label",
                    "status",
                    "status_label",
                    "connector",
                    "project_id",
                    "project_name",
                    "resource_id",
                    "resource_title",
                    "reason",
                    "reason_label",
                    "reason_explanation",
                    "detected_at",
                    "resolved_at",
                    "resolved_by_operation_id"
                ],
                "title": "RecoveryIncidentResource"
            },
            "RecoveryIssue": {
                "type": "string",
                "description": "The three things a platform ban can take from a creator, and the three recoveries the Disaster Recovery Program offers for them. Declared in wizard order. The account comes first because a creator whose own identity is gone cannot act on the connector for the other two until it is replaced; the installation before the resources because customers must be able to reach it before they are re-admitted anywhere.  The backing value is also the quota key: `RecoveryPolicyService` counts operations per kind, so a creator who used one kind still has the other two available inside the same window. The words a creator reads come from the connector's vocabulary, so the same case reads \"Project Bot\" for one connector and \"Project App\" for another; callers without a vocabulary at hand go through `ConnectorRecoverySupport::issueLabel()`.\n",
                "enum": [
                    "account",
                    "bot",
                    "resources"
                ],
                "title": "RecoveryIssue"
            },
            "RecoveryOperationResource": {
                "type": "object",
                "description": "A recovery operation: one recovery run by the creator, by the platform on their behalf, or on demand, with its undo state.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The operation's id, the value the revert, nudge and notify endpoints take.",
                        "examples": [
                            "9a4d2e71-5b38-4c6f-8e12-3d7c9b0a5f21"
                        ]
                    },
                    "kind": {
                        "type": "string",
                        "description": "`account` (a sign-in relink), `bot` (a bot replacement) or `resources` (a channel swap).",
                        "enum": [
                            "account",
                            "bot",
                            "resources"
                        ],
                        "examples": [
                            "resources"
                        ]
                    },
                    "kind_label": {
                        "type": "string",
                        "description": "The kind in the connector's own words, in the creator's language.",
                        "examples": [
                            "Channels and Groups"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "`started` while the recovery runs, then `completed`, `failed` (with `failure_reason`) or `reverted`.",
                        "enum": [
                            "started",
                            "completed",
                            "failed",
                            "reverted"
                        ],
                        "examples": [
                            "completed"
                        ]
                    },
                    "status_label": {
                        "type": "string",
                        "description": "The status in the creator's language.",
                        "enum": [
                            "In progress",
                            "Completed",
                            "Failed",
                            "Reverted"
                        ],
                        "examples": [
                            "Completed"
                        ]
                    },
                    "connector": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The connector the recovery ran on, by key; null when it concerns no connector.",
                        "examples": [
                            "telegram"
                        ]
                    },
                    "project_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The project concerned; null for an account relink.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "project_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "That project's name; null for an account relink.",
                        "examples": [
                            "Research Premium"
                        ]
                    },
                    "grant_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The support grant that paid for the recovery when the self-service allowance was already spent; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "automatic": {
                        "type": "boolean",
                        "description": "True when the platform ran the recovery on the creator's behalf, the failover they sleep through.",
                        "examples": [
                            true
                        ]
                    },
                    "on_demand": {
                        "type": "boolean",
                        "description": "True for a Swap & Grant of a healthy resource, which spends no allowance.",
                        "examples": [
                            false
                        ]
                    },
                    "failure_reason": {
                        "description": "Why a `failed` recovery failed; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "started_at": {
                        "type": "string",
                        "description": "When the recovery started, ISO 8601. The row exists from that moment, because it is the quota ledger and the audit trail at once.",
                        "examples": [
                            "2026-09-12T03:19:10Z"
                        ]
                    },
                    "completed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it finished, ISO 8601; null while running or after failing.",
                        "examples": [
                            "2026-09-12T03:19:42Z"
                        ]
                    },
                    "reverted_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it was undone, ISO 8601; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "revertible": {
                        "type": "boolean",
                        "description": "Whether the creator may still undo it **right now**: completed, of a kind that can be undone (an account relink or a channel swap, never a bot replacement), and inside the undo window. Show the undo exactly when this is true.",
                        "examples": [
                            true
                        ]
                    },
                    "revert_window_ends_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the undo window closes, ISO 8601; null for a recovery that cannot be undone.",
                        "examples": [
                            "2026-09-13T03:19:42Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "kind",
                    "kind_label",
                    "status",
                    "status_label",
                    "connector",
                    "project_id",
                    "project_name",
                    "grant_id",
                    "automatic",
                    "on_demand",
                    "failure_reason",
                    "started_at",
                    "completed_at",
                    "reverted_at",
                    "revertible",
                    "revert_window_ends_at"
                ],
                "title": "RecoveryOperationResource"
            },
            "RecoveryOperationStatus": {
                "type": "string",
                "description": "Where a recovery operation stands. `Started` and `Completed` both count against the self-service quota: an operation is a use the moment it begins, so an abandoned wizard cannot be restarted for free. `Failed` is the one state that gives the use back, because nothing changed. `Reverted` records that the creator undid the change inside the undo window; the use stays consumed.\n",
                "enum": [
                    "started",
                    "completed",
                    "failed",
                    "reverted"
                ],
                "title": "RecoveryOperationStatus"
            },
            "RecoveryReadinessResource": {
                "type": "object",
                "description": "The whole Disaster Recovery readiness checklist for one creator, with the totals the dashboard card shows.",
                "properties": {
                    "prevention": {
                        "type": "boolean",
                        "description": "Whether the plan bundles the prevention features the checklist checks.",
                        "examples": [
                            true
                        ]
                    },
                    "completed": {
                        "type": "integer",
                        "description": "How many verifiable lines are done.",
                        "examples": [
                            4
                        ]
                    },
                    "total": {
                        "type": "integer",
                        "description": "How many lines are verifiable; reminders never count.",
                        "examples": [
                            6
                        ]
                    },
                    "complete": {
                        "type": "boolean",
                        "description": "True when every verifiable line is done.",
                        "examples": [
                            false
                        ]
                    },
                    "items": {
                        "type": "array",
                        "description": "The lines, in the order the dashboard lists them: the account's first, then each installed connector's, then the two reminders.",
                        "items": {}
                    }
                },
                "required": [
                    "prevention",
                    "completed",
                    "total",
                    "complete",
                    "items"
                ],
                "title": "RecoveryReadinessResource"
            },
            "RecoverySettingsResource": {
                "type": "object",
                "description": "A project's Disaster Recovery settings: the switches the Prevention page holds per project. The standby installation's credentials never appear, only the fact that one is registered.",
                "properties": {
                    "project_id": {
                        "type": "string",
                        "description": "The project the settings belong to.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "auto_failover_enabled": {
                        "type": "boolean",
                        "description": "Whether the platform may swap a banned channel for its standby on its own.",
                        "examples": [
                            true
                        ]
                    },
                    "auto_failover_email_consented_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the creator accepted the per-email fee a failover may charge for the members the bot cannot reach, ISO 8601; null until accepted.",
                        "examples": [
                            "2026-09-01T14:20:00Z"
                        ]
                    },
                    "email_delivery": {
                        "type": "string",
                        "description": "How members are told after a channel swap the creator ran: `self` (the creator tells them) or `platform` (Subscriby emails them at the fee).",
                        "enum": [
                            "platform",
                            "self"
                        ],
                        "examples": [
                            "platform"
                        ]
                    },
                    "email_delivery_label": {
                        "type": "string",
                        "description": "That choice in the creator's language.",
                        "enum": [
                            "Email them for me",
                            "I will email them myself"
                        ],
                        "examples": [
                            "Subscriby emails them"
                        ]
                    },
                    "standby_installation_registered": {
                        "type": "boolean",
                        "description": "Whether a spare bot is kept for the project.",
                        "examples": [
                            true
                        ]
                    }
                },
                "required": [
                    "project_id",
                    "auto_failover_enabled",
                    "auto_failover_email_consented_at",
                    "email_delivery",
                    "email_delivery_label",
                    "standby_installation_registered"
                ],
                "title": "RecoverySettingsResource"
            },
            "ReferralAffiliateResource": {
                "type": "object",
                "description": "A member enrolled in the Referral Program: their code, whether they are approved, the membership days they hold on balance and, on a single read, what they are owed per currency. Never their payout details.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The affiliate's id.",
                        "examples": [
                            "0b1c2d3e-4f50-4617-8a9b-0c1d2e3f4a5b"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the programme belongs to.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "program_id": {
                        "type": "string",
                        "description": "The programme they joined.",
                        "examples": [
                            "6e2a7a4f-3b8c-4c21-9f6d-2a3b4c5d6e7f"
                        ]
                    },
                    "member_id": {
                        "type": "string",
                        "description": "The member, as the members endpoints list them.",
                        "examples": [
                            "a1b2c3d4-e5f6-4718-8a9b-0c1d2e3f4a5b"
                        ]
                    },
                    "code": {
                        "type": "string",
                        "description": "The code their friends type at checkout and their links carry; unique within the project.",
                        "examples": [
                            "ADA2026"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "`pending` (awaiting the creator's approval), `approved` (their code counts) or `suspended` (their code no longer counts; what they earned stays).",
                        "enum": [
                            "pending",
                            "approved",
                            "suspended"
                        ],
                        "examples": [
                            "approved"
                        ]
                    },
                    "days_balance": {
                        "type": "integer",
                        "description": "Membership days earned while they held no live membership, banked onto their next purchase.",
                        "examples": [
                            0
                        ]
                    },
                    "balances": {
                        "type": "array",
                        "description": "What they are owed per currency, present on a single read and on every write, not on a list row. Each entry carries `currency_id` and four decimal strings with four places: `pending` (commissions still inside the hold), `earned` (every commission earned in the currency, held, payable or paid), `payable` (past the hold and not yet paid out: what a payout may record) and `paid_out` (recorded as paid).",
                        "items": {}
                    },
                    "joined_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When they joined, ISO 8601.",
                        "examples": [
                            "2026-10-02T11:05:00+00:00"
                        ]
                    },
                    "approved_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the creator approved them, ISO 8601; null while pending.",
                        "examples": [
                            "2026-10-02T11:05:00+00:00"
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the row was written, ISO 8601.",
                        "examples": [
                            "2026-10-02T11:05:00+00:00"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it last changed, ISO 8601.",
                        "examples": [
                            "2026-10-08T16:41:11+00:00"
                        ]
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "program_id",
                    "member_id",
                    "code",
                    "status",
                    "days_balance",
                    "joined_at",
                    "approved_at",
                    "created_at",
                    "updated_at"
                ],
                "title": "ReferralAffiliateResource"
            },
            "ReferralAffiliateStatus": {
                "type": "string",
                "description": "Where a member stands in a project's Referral Program. `Pending` exists only for programmes that require approval; a suspended affiliate keeps their code and their balance but attributes and earns nothing until the creator approves them again.\n",
                "enum": [
                    "pending",
                    "approved",
                    "suspended"
                ],
                "title": "ReferralAffiliateStatus"
            },
            "ReferralBeneficiary": {
                "type": "string",
                "description": "Who a reward row is for: the member who referred, or the member who was referred.\n",
                "enum": [
                    "referrer",
                    "friend"
                ],
                "title": "ReferralBeneficiary"
            },
            "ReferralCommissionType": {
                "type": "string",
                "description": "How a cash commission is worked out from a settled payment. A percentage rides every payment in the commission period, in the currency the payment settled in. A fixed amount is paid once, on the first payment, in the currency the programme names: a fixed sum per renewal would make a weekly plan pay a referrer more than the plan earns.\n",
                "enum": [
                    "percentage",
                    "fixed"
                ],
                "title": "ReferralCommissionType"
            },
            "ReferralFriendRewardKind": {
                "type": "string",
                "description": "What the referred friend receives for arriving through a referral, if anything. Days are banked on the friend's first purchase the moment it settles; a coupon is applied at their checkout and follows the coupon's own rules, which is why it is offered only to creators who hold the Coupons capability.\n",
                "enum": [
                    "none",
                    "free_days",
                    "coupon"
                ],
                "title": "ReferralFriendRewardKind"
            },
            "ReferralPayoutResource": {
                "type": "object",
                "description": "A payout recorded against an affiliate: how much the creator paid them outside Subscriby, in which currency, and how many payable commissions it covered.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The payout's id."
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the programme belongs to."
                    },
                    "affiliate_id": {
                        "type": "string",
                        "description": "The affiliate who was paid."
                    },
                    "amount": {
                        "type": "string",
                        "description": "What was paid, as a decimal string with four places."
                    },
                    "currency_id": {
                        "type": "string",
                        "description": "The currency it was paid in."
                    },
                    "currency": {
                        "type": "string",
                        "description": "That currency's ISO 4217 code, present when the relation is loaded."
                    },
                    "reference": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The creator's own reference, such as a transfer id; null for none."
                    },
                    "note": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The creator's note; null for none."
                    },
                    "paid_at": {
                        "type": "string",
                        "description": "When the payout was recorded, ISO 8601."
                    },
                    "recorded_by_user_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The creator or teammate who recorded it."
                    },
                    "rewards_paid": {
                        "type": "integer",
                        "description": "How many commissions the payout covered, present when the relation is loaded.",
                        "minimum": 0
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the row was written, ISO 8601."
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "affiliate_id",
                    "amount",
                    "currency_id",
                    "reference",
                    "note",
                    "paid_at",
                    "recorded_by_user_id",
                    "created_at"
                ],
                "title": "ReferralPayoutResource"
            },
            "ReferralProgramResource": {
                "type": "object",
                "description": "A project's Referral Program: what referrers earn, what their friends receive on their first purchase, who may join, how long a commission is held, and which plans count.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The programme's id. A project holds one programme.",
                        "examples": [
                            "6e2a7a4f-3b8c-4c21-9f6d-2a3b4c5d6e7f"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project that runs it.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "active": {
                        "type": "boolean",
                        "description": "The creator's on/off switch. A paused programme attributes nothing and earns nothing; what affiliates already earned stays.",
                        "examples": [
                            true
                        ]
                    },
                    "customers_only": {
                        "type": "boolean",
                        "description": "Whether only members with a live membership may join.",
                        "examples": [
                            false
                        ]
                    },
                    "approval_required": {
                        "type": "boolean",
                        "description": "Whether the creator approves each affiliate before their code counts.",
                        "examples": [
                            false
                        ]
                    },
                    "reward_kind": {
                        "type": "string",
                        "description": "`free_days` (membership days banked on the referrer) or `cash` (a commission the creator pays out themselves).",
                        "enum": [
                            "free_days",
                            "cash"
                        ],
                        "examples": [
                            "cash"
                        ]
                    },
                    "reward_days": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Days a referrer earns per converted friend on a `free_days` programme; null on a cash one.",
                        "examples": [
                            null
                        ]
                    },
                    "commission_type": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "`percentage` of every settled payment or a `fixed` amount on the first; null on a `free_days` programme.",
                        "enum": [
                            "percentage",
                            "fixed",
                            null
                        ],
                        "examples": [
                            "percentage"
                        ]
                    },
                    "commission_value": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The rate as a decimal string with four places: `\"20.0000\"` for 20%, `\"10.0000\"` for ten of the commission currency. Parse it as a decimal, never a float.",
                        "examples": [
                            "20.0000"
                        ]
                    },
                    "commission_currency_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The currency a `fixed` commission is paid in; null for a percentage, which is earned in each payment's own currency.",
                        "examples": [
                            null
                        ]
                    },
                    "commission_currency": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "That currency's ISO 4217 code, present only when the relation is loaded: on a single read and every write, not on a list row.",
                        "examples": [
                            null
                        ]
                    },
                    "commission_period_months": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "How long a percentage commission runs after conversion: `0` for the friend's first payment only, a number of months, or null for life. Always `0` on a fixed commission.",
                        "examples": [
                            6
                        ]
                    },
                    "hold_days": {
                        "type": "integer",
                        "description": "Days a cash commission waits before it is payable, so a refund inside the window can take it back.",
                        "examples": [
                            14
                        ]
                    },
                    "minimum_payout": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A guide for the creator, the balance an affiliate reaches before they pay; nothing is enforced. Null for none.",
                        "examples": [
                            "50.0000"
                        ]
                    },
                    "friend_reward_kind": {
                        "type": "string",
                        "description": "What a referred friend receives on their first purchase: `none`, `free_days` or `coupon`.",
                        "enum": [
                            "none",
                            "free_days",
                            "coupon"
                        ],
                        "examples": [
                            "free_days"
                        ]
                    },
                    "friend_reward_days": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Days banked on the friend's first purchase on a `free_days` friend reward; null otherwise.",
                        "examples": [
                            3
                        ]
                    },
                    "friend_coupon_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The coupon applied at the friend's checkout on a `coupon` friend reward; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "payout_details_label": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The question affiliates answer so the creator can pay them, such as `PayPal email`; null for none.",
                        "examples": [
                            "PayPal email"
                        ]
                    },
                    "terms": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The creator's own terms, shown to affiliates and referred friends; null for none.",
                        "examples": [
                            "One referral per household."
                        ]
                    },
                    "plan_ids": {
                        "type": "object",
                        "description": "The plans a conversion must be on to count. An empty array means **every** plan in the project, including plans added later, not no plans.",
                        "additionalProperties": {}
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the programme was set up, ISO 8601.",
                        "examples": [
                            "2026-10-01T09:14:02+00:00"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it last changed, ISO 8601.",
                        "examples": [
                            "2026-10-08T16:41:11+00:00"
                        ]
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "active",
                    "customers_only",
                    "approval_required",
                    "reward_kind",
                    "reward_days",
                    "commission_type",
                    "commission_value",
                    "commission_currency_id",
                    "commission_period_months",
                    "hold_days",
                    "minimum_payout",
                    "friend_reward_kind",
                    "friend_reward_days",
                    "friend_coupon_id",
                    "payout_details_label",
                    "terms",
                    "plan_ids",
                    "created_at",
                    "updated_at"
                ],
                "title": "ReferralProgramResource"
            },
            "ReferralResource": {
                "type": "object",
                "description": "A referral: a friend who arrived through an affiliate's link or code, whether their first payment settled, and until when the affiliate earns on them.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The referral's id."
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the programme belongs to."
                    },
                    "program_id": {
                        "type": "string",
                        "description": "The programme the affiliate earns under."
                    },
                    "affiliate_id": {
                        "type": "string",
                        "description": "The affiliate who referred the friend."
                    },
                    "member_id": {
                        "type": "string",
                        "description": "The friend, as the members endpoints list them."
                    },
                    "source": {
                        "type": "string",
                        "description": "How the friend arrived: `portal_link`, `connector_link` or `code_at_checkout`.",
                        "enum": [
                            "connector_link",
                            "portal_link",
                            "code_at_checkout"
                        ]
                    },
                    "connector": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The connector whose link they came through, such as a bot's deep link; null for the portal or a typed code."
                    },
                    "status": {
                        "type": "string",
                        "description": "`touched` (arrived, not yet paid), `converted` (first payment settled), `expired` (the attribution window passed) or `rejected`.",
                        "enum": [
                            "touched",
                            "converted",
                            "expired",
                            "rejected"
                        ]
                    },
                    "touched_at": {
                        "type": "string",
                        "description": "When the friend arrived, ISO 8601."
                    },
                    "expires_at": {
                        "type": "string",
                        "description": "When the attribution lapses unless they pay, ISO 8601."
                    },
                    "converted_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When their first payment settled, ISO 8601; null until then."
                    },
                    "converted_subscription_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The purchase that converted them; null until then."
                    },
                    "commission_ends_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "On a cash programme with a period, when the affiliate stops earning on this friend, ISO 8601; null for life, for a first-payment-only commission, or before conversion."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the row was written, ISO 8601."
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "program_id",
                    "affiliate_id",
                    "member_id",
                    "source",
                    "connector",
                    "status",
                    "touched_at",
                    "expires_at",
                    "converted_at",
                    "converted_subscription_id",
                    "commission_ends_at",
                    "created_at"
                ],
                "title": "ReferralResource"
            },
            "ReferralRewardKind": {
                "type": "string",
                "description": "What a referrer earns per referral: membership time, or money the creator pays out. Two kinds and no third, because every other shape a creator asked for (a coupon for the referrer, store credit) is one of these in disguise and each adds a surface the Payouts tab would have to explain.\n",
                "enum": [
                    "free_days",
                    "cash"
                ],
                "title": "ReferralRewardKind"
            },
            "ReferralRewardResource": {
                "type": "object",
                "description": "A reward in the referral ledger: the days or money one settled payment earned the referrer or their friend, and where it stands.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The reward's id."
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the programme belongs to."
                    },
                    "program_id": {
                        "type": "string",
                        "description": "The programme it was earned under."
                    },
                    "affiliate_id": {
                        "type": "string",
                        "description": "The affiliate whose referral earned it."
                    },
                    "referral_id": {
                        "type": "string",
                        "description": "The referral it was earned on."
                    },
                    "payment_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The settled payment that earned it; null on a reversal."
                    },
                    "beneficiary": {
                        "type": "string",
                        "description": "`referrer` or `friend`.",
                        "enum": [
                            "referrer",
                            "friend"
                        ]
                    },
                    "kind": {
                        "type": "string",
                        "description": "`free_days` or `cash`.",
                        "enum": [
                            "free_days",
                            "cash"
                        ]
                    },
                    "days": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The days, on a `free_days` reward; null on a cash one."
                    },
                    "amount": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The money as a decimal string with four places, on a `cash` reward; negative on a reversal. Null on a days reward."
                    },
                    "currency_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The currency of a cash reward; null on a days reward."
                    },
                    "currency": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "That currency's ISO 4217 code, present when the relation is loaded."
                    },
                    "status": {
                        "type": "string",
                        "description": "`pending` (inside the hold, or days waiting on the balance), `approved` (payable), `paid` (recorded in a payout), `applied` (days banked on a membership) or `reversed` (taken back by a refund).",
                        "enum": [
                            "pending",
                            "approved",
                            "paid",
                            "reversed",
                            "applied"
                        ]
                    },
                    "hold_until": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a held cash reward becomes payable, ISO 8601; null otherwise."
                    },
                    "approved_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it became payable, ISO 8601."
                    },
                    "paid_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a payout recorded it, ISO 8601."
                    },
                    "reversed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a refund reversed it, ISO 8601."
                    },
                    "applied_subscription_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The membership the days were banked on; null until applied or on a cash reward."
                    },
                    "reverses_reward_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "On a reversal row, the reward it cancels."
                    },
                    "payout_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The payout that paid it; null until then."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the row was written, ISO 8601."
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "program_id",
                    "affiliate_id",
                    "referral_id",
                    "payment_id",
                    "beneficiary",
                    "kind",
                    "days",
                    "amount",
                    "currency_id",
                    "status",
                    "hold_until",
                    "approved_at",
                    "paid_at",
                    "reversed_at",
                    "applied_subscription_id",
                    "reverses_reward_id",
                    "payout_id",
                    "created_at"
                ],
                "title": "ReferralRewardResource"
            },
            "ReferralRewardStatus": {
                "type": "string",
                "description": "Where a reward row stands. Cash moves `Pending` → `Approved` → `Paid`, or to `Reversed` when the payment behind it is refunded before it was paid out; days move `Pending` (waiting on the affiliate's balance) → `Applied` (banked on a purchase).\n",
                "enum": [
                    "pending",
                    "approved",
                    "paid",
                    "reversed",
                    "applied"
                ],
                "title": "ReferralRewardStatus"
            },
            "ReferralStatus": {
                "type": "string",
                "description": "What became of a referral touch. `Touched` is an attribution waiting for a first payment inside the window; `Converted` has one and may keep earning for the commission period; `Expired` ran out of window; `Rejected` was refused after the fact (a self-referral found later, an abuse review).\n",
                "enum": [
                    "touched",
                    "converted",
                    "expired",
                    "rejected"
                ],
                "title": "ReferralStatus"
            },
            "RegisterBackupIdentityRequest": {
                "type": "object",
                "description": "Which completed backup handshake names the account to keep as the backup.",
                "properties": {
                    "handshake_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "A `backup` handshake of the caller's in state `completed`; the account that tapped it becomes the backup."
                    }
                },
                "required": [
                    "handshake_id"
                ],
                "title": "RegisterBackupIdentityRequest"
            },
            "ReissueSubscriptionGrantsRequest": {
                "type": "object",
                "description": "Which access to reissue: one resource of the plan, or every resource the purchase grants when the body is empty.",
                "properties": {
                    "resource_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uuid",
                        "description": "A resource the plan grants, to reissue it alone; omit it to reissue every resource. A resource the plan does not grant answers 404."
                    }
                },
                "title": "ReissueSubscriptionGrantsRequest"
            },
            "ReorderPlansRequest": {
                "type": "object",
                "description": "The storefront order: every plan to pin, first to last.",
                "properties": {
                    "plan_ids": {
                        "type": "array",
                        "description": "Plan ids in storefront order, at most 200, each a plan of this project and none repeated. An empty list clears every pin.",
                        "items": {
                            "type": "string",
                            "description": "A plan id."
                        },
                        "maxItems": 200,
                        "uniqueItems": true
                    }
                },
                "required": [
                    "plan_ids"
                ],
                "title": "ReorderPlansRequest"
            },
            "RequestResourceLinkRequest": {
                "type": "object",
                "description": "Which kind of place to ask the creator for. Only a connector's kind can be requested; a manual perk is created outright with the create endpoint.",
                "properties": {
                    "kind": {
                        "type": "string",
                        "description": "A connector's kind of place spelled `connector:kind`, as the connector directory lists each connector's `resource_kinds`. `manual` and a bare kind word are refused.",
                        "pattern": "^[a-z][a-z0-9_-]*:[a-z][a-z0-9_-]*$"
                    }
                },
                "required": [
                    "kind"
                ],
                "title": "RequestResourceLinkRequest"
            },
            "ResourceResource": {
                "type": "object",
                "description": "A resource a project sells access to: a place a connector gates, or a manual perk the creator hands over by hand.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The resource's id.",
                        "examples": [
                            "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the resource belongs to.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "kind": {
                        "type": "string",
                        "description": "`manual` for a perk the creator hands over by hand, otherwise `connector:kind` as the connector directory lists each connector's `resource_kinds`.",
                        "examples": [
                            "telegram:channel"
                        ]
                    },
                    "connector": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The connector key the place is on; null for a manual perk.",
                        "examples": [
                            "telegram"
                        ]
                    },
                    "space": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The place the resource is bound to. Null for a manual perk and for a place-kind resource that was unlinked.",
                        "examples": [
                            null
                        ],
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The space's id.",
                                "examples": [
                                    "3c1f7a58-2b6e-4d90-8f41-6a2e9c5d7b10"
                                ]
                            },
                            "external_id": {
                                "type": "string",
                                "description": "The platform's own id for the place.",
                                "examples": [
                                    "-1001234567890"
                                ]
                            },
                            "title": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The place's title as the connector last read it.",
                                "examples": [
                                    "Research Premium Lounge"
                                ]
                            }
                        },
                        "required": [
                            "id",
                            "external_id",
                            "title"
                        ]
                    },
                    "title": {
                        "type": "string",
                        "description": "The resource's name on plan cards; for a linked place, the place's title at link time.",
                        "examples": [
                            "Research Premium Lounge"
                        ]
                    },
                    "description": {
                        "description": "Up to 1,000 characters of well-formed HTML, shown as a perk beside the title; null when none.",
                        "anyOf": [
                            {
                                "type": "string",
                                "examples": [
                                    "Daily research notes and the members-only Q&A."
                                ]
                            },
                            {
                                "type": "array"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "active": {
                        "type": "boolean",
                        "description": "Whether plans grant it right now. An inactive resource keeps its link and its plans, but new members do not receive it.",
                        "examples": [
                            true
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the resource was created, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the resource last changed, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "kind",
                    "connector",
                    "space",
                    "title",
                    "description",
                    "active",
                    "created_at",
                    "updated_at"
                ],
                "title": "ResourceResource"
            },
            "ResourceStandbyResource": {
                "type": "object",
                "description": "The standby space kept ready for one resource: whether it is healthy and mirrored, and when it was last probed and written to. Its identifier on the platform stays out.",
                "properties": {
                    "resource_id": {
                        "type": "string",
                        "description": "The resource the standby is kept for.",
                        "examples": [
                            "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6"
                        ]
                    },
                    "mirror_enabled": {
                        "type": "boolean",
                        "description": "Whether every post made in the channel is copied into the standby as it is made.",
                        "examples": [
                            true
                        ]
                    },
                    "health_status": {
                        "type": "string",
                        "description": "`healthy`, `degraded` or `detached`, as the last probe found it; null before the first probe.",
                        "enum": [
                            "healthy",
                            "degraded",
                            "detached"
                        ],
                        "examples": [
                            "healthy"
                        ]
                    },
                    "health_status_label": {
                        "type": "string",
                        "description": "The status in the creator's language.",
                        "enum": [
                            "Healthy",
                            "Degraded",
                            "Detached"
                        ],
                        "examples": [
                            "Healthy"
                        ]
                    },
                    "health_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The connector's code for a degraded or detached standby, such as `chat_not_found`, `bot_removed`, `bot_not_administrator`, `bot_missing_rights` or `connector_api_error`; null while healthy.",
                        "enum": [
                            "chat_not_found",
                            "bot_removed",
                            "bot_not_administrator",
                            "bot_missing_rights",
                            "connector_api_error",
                            null
                        ],
                        "examples": [
                            null
                        ]
                    },
                    "health_checked_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the standby was last probed, ISO 8601; null before the first probe.",
                        "examples": [
                            "2026-09-12T02:00:00Z"
                        ]
                    },
                    "last_mirrored_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a post was last copied into the standby, ISO 8601; null if never.",
                        "examples": [
                            "2026-09-12T01:45:12Z"
                        ]
                    },
                    "linked_at": {
                        "type": "string",
                        "description": "When the standby was linked, ISO 8601.",
                        "examples": [
                            "2026-09-01T14:22:09Z"
                        ]
                    }
                },
                "required": [
                    "resource_id",
                    "mirror_enabled",
                    "health_status",
                    "health_status_label",
                    "health_reason",
                    "health_checked_at",
                    "last_mirrored_at",
                    "linked_at"
                ],
                "title": "ResourceStandbyResource"
            },
            "RestoreReportResource": {
                "type": "object",
                "description": "What restoring access after a reinstall did: which detached places came back and how many live purchases were handed fresh access.",
                "properties": {
                    "installation": {
                        "type": "array",
                        "description": "The installation the connector was asked through, in the installation object's shape.",
                        "items": {}
                    },
                    "connector": {
                        "type": "string",
                        "description": "The connector's key.",
                        "examples": [
                            "example"
                        ]
                    },
                    "resources": {
                        "type": "array",
                        "description": "Every place the uninstall had detached, with whether the connector still controls it.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "resource_id": {
                                    "type": "string",
                                    "description": "The resource's id.",
                                    "examples": [
                                        "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6"
                                    ]
                                },
                                "title": {
                                    "type": "string",
                                    "description": "The resource's title.",
                                    "examples": [
                                        "Premium Channel"
                                    ]
                                },
                                "restored": {
                                    "type": "boolean",
                                    "description": "True when the connector still controls the place and it was made active and healthy again; false when it stays detached for the doctor to explain.",
                                    "examples": [
                                        true
                                    ]
                                }
                            },
                            "required": [
                                "resource_id",
                                "title",
                                "restored"
                            ]
                        }
                    },
                    "resources_reactivated": {
                        "type": "integer",
                        "description": "How many places came back.",
                        "examples": [
                            1
                        ]
                    },
                    "resources_still_detached": {
                        "type": "integer",
                        "description": "How many places the connector no longer controls.",
                        "examples": [
                            1
                        ]
                    },
                    "subscriptions_reissued": {
                        "type": "integer",
                        "description": "How many live purchases were handed the grants the uninstall took away.",
                        "examples": [
                            14
                        ]
                    }
                },
                "required": [
                    "installation",
                    "connector",
                    "resources",
                    "resources_reactivated",
                    "resources_still_detached",
                    "subscriptions_reissued"
                ],
                "title": "RestoreReportResource"
            },
            "RetentionSettingsResource": {
                "type": "object",
                "description": "A project's Revenue Recovery settings: how long a failed renewal keeps access, the notice ladder that follows in words, whether the daily digest is sent, what the cancellation screen asks, which of the three offers it makes, how long a checkout may stay open before it counts as stalled, and how many days before a trial without a card ends its sequence starts.",
                "properties": {
                    "project_id": {
                        "type": "string",
                        "description": "The project the settings belong to.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "grace_days": {
                        "type": "integer",
                        "description": "How many days a failed renewal keeps access while the gateway retries, 0 to 30. `0` pauses access at the failure.",
                        "examples": [
                            7
                        ]
                    },
                    "ladder": {
                        "type": "string",
                        "description": "The grace window and its notices in words, as the dashboard and the bot say them.",
                        "examples": [
                            "A failed renewal keeps access for 7 days: a notice at the failure, a reminder on day 3, a final warning on the last day, then access pauses until a charge settles."
                        ]
                    },
                    "digest_enabled": {
                        "type": "boolean",
                        "description": "Whether the owner gets one message a day with the failures, reminders, pauses and recoveries, only on a day something happened.",
                        "examples": [
                            true
                        ]
                    },
                    "cancel_feedback_enabled": {
                        "type": "boolean",
                        "description": "Whether the cancellation screen asks the member why before the offer.",
                        "examples": [
                            true
                        ]
                    },
                    "checkout_stall_hours": {
                        "type": "integer",
                        "description": "How many hours a checkout may stay open with no settled charge before the hourly sweep counts it as stalled and the stalled-checkout sequences start, 1 to 24.",
                        "examples": [
                            1
                        ]
                    },
                    "trial_notice_days": {
                        "type": "integer",
                        "description": "How many days before a trial without a card ends its trial-ending sequences start, 1 to 14. A trial shorter than that enrols at its start.",
                        "examples": [
                            3
                        ]
                    },
                    "offers_available": {
                        "type": "boolean",
                        "description": "Whether the project owner's plan includes the offers (Growth or the Revenue Recovery Addon). The three offer settings are stored either way and ignored by the screen without it.",
                        "examples": [
                            true
                        ]
                    },
                    "offer_pause_enabled": {
                        "type": "boolean",
                        "description": "Whether a cancelling member on Stripe or PayPal is offered one billing cycle on hold.",
                        "examples": [
                            true
                        ]
                    },
                    "offer_discount_coupon": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The coupon applied to a cancelling member's renewals where Stripe can carry it, or `null` for no discount offer.",
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The coupon's id.",
                                "examples": [
                                    "3b7c9d1e-5f24-4a86-9c0b-2d4e6f8a1b3c"
                                ]
                            },
                            "code": {
                                "type": "string",
                                "description": "The coupon's code.",
                                "examples": [
                                    "STAY20"
                                ]
                            }
                        },
                        "required": [
                            "id",
                            "code"
                        ]
                    },
                    "offer_return_coupon": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The coupon handed to a cancelling member on every payment method, to come back with, or `null` for no return coupon.",
                        "examples": [
                            null
                        ],
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The coupon's id."
                            },
                            "code": {
                                "type": "string",
                                "description": "The coupon's code."
                            }
                        },
                        "required": [
                            "id",
                            "code"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the settings last changed, ISO 8601.",
                        "examples": [
                            "2026-10-12T09:00:00+00:00"
                        ]
                    }
                },
                "required": [
                    "project_id",
                    "grace_days",
                    "ladder",
                    "digest_enabled",
                    "cancel_feedback_enabled",
                    "checkout_stall_hours",
                    "trial_notice_days",
                    "offers_available",
                    "offer_pause_enabled",
                    "updated_at"
                ],
                "title": "RetentionSettingsResource"
            },
            "RetentionStatsResource": {
                "type": "object",
                "description": "What Revenue Recovery did on a project over the window: the failed renewals and what the recovered ones brought back in US dollars, why members cancelled, the members in grace or paused right now, and the leads, checkouts and trials the sequences nurtured with what the recovered checkouts were worth.",
                "properties": {
                    "period": {
                        "type": "string",
                        "description": "The preset the figures cover.",
                        "enum": [
                            "7d",
                            "14d",
                            "30d",
                            "60d",
                            "90d",
                            "1y",
                            "mtd",
                            "qtd",
                            "ytd",
                            "all"
                        ]
                    },
                    "range": {
                        "type": "object",
                        "description": "The window's bounds.",
                        "properties": {
                            "from": {
                                "type": "string",
                                "description": "The first day, ISO 8601 date."
                            },
                            "to": {
                                "type": "string",
                                "description": "The last day, ISO 8601 date."
                            }
                        },
                        "required": [
                            "from",
                            "to"
                        ]
                    },
                    "failed_renewals": {
                        "type": "integer",
                        "description": "Renewals the gateway could not collect in the window."
                    },
                    "reminders_sent": {
                        "type": "integer",
                        "description": "The day-three reminders and final warnings sent."
                    },
                    "access_paused": {
                        "type": "integer",
                        "description": "Grace windows that closed unpaid, pausing access."
                    },
                    "payments_recovered": {
                        "type": "integer",
                        "description": "Failed renewals settled later in the window."
                    },
                    "recovered_usd": {
                        "type": "string",
                        "description": "What those settled renewals were worth, restated in US dollars, a decimal string with two places."
                    },
                    "access_restored": {
                        "type": "integer",
                        "description": "Paused members let back in."
                    },
                    "in_grace_now": {
                        "type": "integer",
                        "description": "Members who keep access on an unpaid renewal right now; not windowed."
                    },
                    "paused_now": {
                        "type": "integer",
                        "description": "Members paused for non-payment right now, waiting for a charge to settle; not windowed."
                    },
                    "winback_sent": {
                        "type": "integer",
                        "description": "Win-back sequence steps delivered on the churn trigger."
                    },
                    "won_back": {
                        "type": "integer",
                        "description": "Members a win-back sequence brought back: churn passages that ended because the member paid again."
                    },
                    "cancellations": {
                        "type": "integer",
                        "description": "Cancellation screens recorded."
                    },
                    "offers_shown": {
                        "type": "integer",
                        "description": "Cancellation screens that made an offer."
                    },
                    "offers_taken": {
                        "type": "integer",
                        "description": "Offers the member took."
                    },
                    "reasons": {
                        "type": "array",
                        "description": "Why members cancelled, the most given reason first.",
                        "items": {
                            "$ref": "#/components/schemas/CancellationReasonShareResource"
                        }
                    },
                    "leads_arrived": {
                        "type": "integer",
                        "description": "Members who arrived as leads in the window, through any door."
                    },
                    "leads_nurtured": {
                        "type": "integer",
                        "description": "Leads a lead sequence took."
                    },
                    "leads_converted": {
                        "type": "integer",
                        "description": "Leads who bought while a lead sequence ran: lead passages that ended because a charge settled."
                    },
                    "checkouts_started": {
                        "type": "integer",
                        "description": "Checkouts members started on the portal or in a bot."
                    },
                    "checkouts_stalled": {
                        "type": "integer",
                        "description": "Checkouts the hourly sweep counted as stalled, once the project's window passed with no settled charge."
                    },
                    "checkouts_recovered": {
                        "type": "integer",
                        "description": "Stalled checkouts a charge finished after all."
                    },
                    "checkouts_recovered_usd": {
                        "type": "string",
                        "description": "What the charges that finished the stalled checkouts were worth, restated in US dollars, a decimal string with two places."
                    },
                    "trials_nurtured": {
                        "type": "integer",
                        "description": "Trials without a card a trial-ending sequence took."
                    },
                    "trials_saved": {
                        "type": "integer",
                        "description": "Trials whose member paid while the sequence ran: trial passages that ended because a charge settled."
                    }
                },
                "required": [
                    "period",
                    "range",
                    "failed_renewals",
                    "reminders_sent",
                    "access_paused",
                    "payments_recovered",
                    "recovered_usd",
                    "access_restored",
                    "in_grace_now",
                    "paused_now",
                    "winback_sent",
                    "won_back",
                    "cancellations",
                    "offers_shown",
                    "offers_taken",
                    "reasons",
                    "leads_arrived",
                    "leads_nurtured",
                    "leads_converted",
                    "checkouts_started",
                    "checkouts_stalled",
                    "checkouts_recovered",
                    "checkouts_recovered_usd",
                    "trials_nurtured",
                    "trials_saved"
                ],
                "title": "RetentionStatsResource"
            },
            "RetentionTouchKind": {
                "type": "string",
                "description": "What a row of the Revenue Recovery ledger records. The four ladder kinds are the notices a member receives about an unpaid renewal, in the order they can arrive; the ledger holds each at most once per failure, which is how a notice is never repeated. `AccessRestored` and `PaymentRecovered` close an episode: the first says the member was let back in, the second that money arrived, and a recovery during the grace window records only the second because nothing was taken away. The offer, feedback and sequence kinds are written by the cancellation screen and the win-back sequences; they are declared here from the first migration because the column's check constraint cannot be widened later.\n",
                "enum": [
                    "payment_failed_notice",
                    "grace_reminder",
                    "grace_final_warning",
                    "access_suspended",
                    "access_restored",
                    "payment_recovered",
                    "offer_shown",
                    "offer_taken",
                    "feedback",
                    "sequence_step"
                ],
                "title": "RetentionTouchKind"
            },
            "RetentionTouchResource": {
                "type": "object",
                "description": "One row of the Revenue Recovery ledger: a notice, an offer or a win-back message the programme sent, who received it, how, and whether the member paid again afterwards.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The row's id."
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project."
                    },
                    "subscription_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The membership the row is about, or `null` for a win-back message to a member who holds none."
                    },
                    "member": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The member, present when the relation is loaded.",
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The member's project-scoped id."
                            },
                            "name": {
                                "type": "string",
                                "description": "The member's display name."
                            }
                        },
                        "required": [
                            "id",
                            "name"
                        ]
                    },
                    "kind": {
                        "type": "string",
                        "description": "What happened: `payment_failed_notice`, `grace_reminder`, `grace_final_warning`, `access_suspended`, `access_restored`, `payment_recovered`, `offer_shown`, `offer_taken`, `feedback` or `sequence_step`.",
                        "enum": [
                            "payment_failed_notice",
                            "grace_reminder",
                            "grace_final_warning",
                            "access_suspended",
                            "access_restored",
                            "payment_recovered",
                            "offer_shown",
                            "offer_taken",
                            "feedback",
                            "sequence_step"
                        ]
                    },
                    "channel": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What carried a notice: `chat` or `email`; `null` for a row that sent nothing.",
                        "enum": [
                            "chat",
                            "email",
                            null
                        ]
                    },
                    "sent_at": {
                        "type": "string",
                        "description": "When the row was written, ISO 8601."
                    },
                    "converted_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a charge settled after this row and counted it as converted, ISO 8601; `null` until then."
                    },
                    "payment_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The payment that converted the row, or `null`."
                    },
                    "coupon": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The coupon a win-back step carried, present when the relation is loaded; `null` without one.",
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The coupon's id."
                            },
                            "code": {
                                "type": "string",
                                "description": "The coupon's code."
                            }
                        },
                        "required": [
                            "id",
                            "code"
                        ]
                    },
                    "step": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The sequence step behind a win-back message, present when the relation is loaded; `null` for every other kind.",
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The step's id."
                            },
                            "sequence_id": {
                                "type": "string",
                                "description": "The sequence it belongs to."
                            },
                            "position": {
                                "type": "integer",
                                "description": "The step's place in the sequence."
                            }
                        },
                        "required": [
                            "id",
                            "sequence_id",
                            "position"
                        ]
                    },
                    "meta": {
                        "type": [
                            "array",
                            "null"
                        ],
                        "description": "What else the row knows, by kind: the offer and the cancellation record for the cancellation rows, the sequence and the enrolment for a win-back message, the repair link for a notice; `null` when there is nothing more.",
                        "items": {}
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "subscription_id",
                    "kind",
                    "channel",
                    "sent_at",
                    "converted_at",
                    "payment_id",
                    "meta"
                ],
                "title": "RetentionTouchResource"
            },
            "RetryDeadWebhookDeliveriesRequest": {
                "type": "object",
                "description": "How far back to replay. Optional: omitted, the last 24 hours are replayed, the dashboard's Replay window.",
                "properties": {
                    "since": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "ISO 8601, not in the future. Only rows dead-lettered **at or after** this instant are replayed. Omit it for the last 24 hours."
                    }
                },
                "title": "RetryDeadWebhookDeliveriesRequest"
            },
            "RevertRecoveryOperationRequest": {
                "type": "object",
                "description": "Which part of a recovery to undo. A channel recovery is undone one swap at a time and names the resource; an account relink is undone whole and takes an empty body.",
                "properties": {
                    "resource_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uuid",
                        "description": "For a channel recovery, the resource to put back on its old chat; every active member is re-admitted there again. Omit it for an account relink."
                    }
                },
                "title": "RevertRecoveryOperationRequest"
            },
            "RoleResource": {
                "type": "object",
                "description": "A role: the permission set one collaborator holds on a team. Every team seeds `admin`, `manager` and `viewer`, and creators add their own.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The role's id.",
                        "examples": [
                            "d05e1a83-7c46-4f29-b613-8ae407c9d251"
                        ]
                    },
                    "team_id": {
                        "type": "string",
                        "description": "The team the role belongs to.",
                        "examples": [
                            "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86"
                        ]
                    },
                    "code": {
                        "type": "string",
                        "description": "The stable identifier permissions are addressed by, unique within the team and immutable after creation.",
                        "examples": [
                            "manager"
                        ]
                    },
                    "name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The display name.",
                        "examples": [
                            "Manager"
                        ]
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the role is for; null when none was given.",
                        "examples": [
                            "Manage plans, resources, and subscribers"
                        ]
                    },
                    "owner_user_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The user who created the role, the only one besides the team owner who may delete it.",
                        "examples": [
                            "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                        ]
                    },
                    "permissions": {
                        "type": "array",
                        "description": "The exact ability strings the role grants, the same strings used as token abilities, so roles can be matched against tokens without a second round-trip.",
                        "items": {
                            "description": "A permission code in `entity:action` form.",
                            "examples": [
                                "project:view"
                            ]
                        }
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the role was created, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "team_id",
                    "code",
                    "name",
                    "description",
                    "owner_user_id",
                    "permissions",
                    "created_at"
                ],
                "title": "RoleResource"
            },
            "SequenceEnrollmentResource": {
                "type": "object",
                "description": "One member's passage through a win-back sequence: when they entered, which step is due next, and how the passage ended if it has.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The passage's id, the `enrollment_id` of the sequence events."
                    },
                    "sequence_id": {
                        "type": "string",
                        "description": "The sequence."
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project."
                    },
                    "member": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The member, present when the relation is loaded.",
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The member's project-scoped id."
                            },
                            "name": {
                                "type": "string",
                                "description": "The member's display name."
                            }
                        },
                        "required": [
                            "id",
                            "name"
                        ]
                    },
                    "subscription_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The membership whose end enrolled the member, or `null`."
                    },
                    "state": {
                        "type": "string",
                        "description": "`open` (steps still to come), `completed` (every step received) or `exited` (ended before the last step; see `exit_reason`).",
                        "enum": [
                            "completed",
                            "open",
                            "exited"
                        ]
                    },
                    "enrolled_at": {
                        "type": "string",
                        "description": "When the member entered, ISO 8601."
                    },
                    "next_position": {
                        "type": "integer",
                        "description": "The step due next while open."
                    },
                    "next_due_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When that step falls due, ISO 8601; `null` once the passage ended."
                    },
                    "completed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the last step went out, ISO 8601; `null` otherwise."
                    },
                    "exited_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the passage ended early, ISO 8601; `null` otherwise."
                    },
                    "exit_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why it ended early: `reactivated` (a charge settled for the member: a member won back on a churn passage, a conversion on a lead, checkout or trial one), `opted_out` (the member could not be reached, or pressed Stop), `disabled` (the sequence was switched off) or `deleted`; `null` otherwise.",
                        "enum": [
                            "completed",
                            "reactivated",
                            "opted_out",
                            "disabled",
                            "deleted",
                            null
                        ]
                    }
                },
                "required": [
                    "id",
                    "sequence_id",
                    "project_id",
                    "subscription_id",
                    "state",
                    "enrolled_at",
                    "next_position",
                    "next_due_at",
                    "completed_at",
                    "exited_at",
                    "exit_reason"
                ],
                "title": "SequenceEnrollmentResource"
            },
            "SequenceExit": {
                "type": "string",
                "description": "Why a member's enrolment in a sequence ended. Completed means every step went out; reactivated means a payment settled for the member and the sequence worked, so the steps that went out are converted; the other three stop the steps without a conversion: the member opted out of announcements, the creator switched the sequence off, or deleted it.\n",
                "enum": [
                    "completed",
                    "reactivated",
                    "opted_out",
                    "disabled",
                    "deleted"
                ],
                "title": "SequenceExit"
            },
            "SequenceResource": {
                "type": "object",
                "description": "A sequence: the ordered messages a member receives on the days the creator chose after one of four moments (they left, they arrived as a lead, their checkout stalled, their trial is about to end), each with the way to the plan and, optionally, a coupon; with how many members it enrolled, how many are still receiving it and how many paid while it ran.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The sequence's id.",
                        "examples": [
                            "9d2f4b6a-1c3e-4f58-8a7b-6e5d4c3b2a19"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the sequence belongs to.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "name": {
                        "type": "string",
                        "description": "A creator-facing label.",
                        "examples": [
                            "Win-back after churn"
                        ]
                    },
                    "trigger": {
                        "type": "string",
                        "description": "What enrols a member: `churned` (their last live membership ended), `lead` (they arrived without buying), `stalled_checkout` (a checkout stayed open past the project's window) or `trial_ending` (a trial without a card is about to end).",
                        "enum": [
                            "churned",
                            "lead",
                            "stalled_checkout",
                            "trial_ending"
                        ],
                        "examples": [
                            "churned"
                        ]
                    },
                    "active": {
                        "type": "boolean",
                        "description": "Whether the sequence enrols and sends.",
                        "examples": [
                            true
                        ]
                    },
                    "steps": {
                        "type": "array",
                        "description": "The steps in order, present when the relation is loaded.",
                        "items": {
                            "$ref": "#/components/schemas/SequenceStepResource"
                        }
                    },
                    "counts": {
                        "type": "object",
                        "description": "How the sequence has done, all time.",
                        "properties": {
                            "enrolled": {
                                "type": "string",
                                "description": "Every member ever enrolled."
                            },
                            "open": {
                                "type": "string",
                                "description": "Members still receiving steps."
                            },
                            "completed": {
                                "type": "string",
                                "description": "Members who received every step."
                            },
                            "won_back": {
                                "type": "string",
                                "description": "Members for whom a payment settled while the sequence ran."
                            }
                        },
                        "required": [
                            "enrolled",
                            "open",
                            "completed",
                            "won_back"
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the sequence was built, ISO 8601.",
                        "examples": [
                            "2026-10-01T09:00:00+00:00"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it last changed, ISO 8601.",
                        "examples": [
                            "2026-10-10T08:00:00+00:00"
                        ]
                    },
                    "deleted_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the creator deleted it, ISO 8601; `null` while in use.",
                        "examples": [
                            null
                        ]
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "name",
                    "trigger",
                    "active",
                    "counts",
                    "created_at",
                    "updated_at",
                    "deleted_at"
                ],
                "title": "SequenceResource"
            },
            "SequenceStepResource": {
                "type": "object",
                "description": "One step of a win-back sequence: its place, how many days it waits, the message in the creator's words and the coupon it carries.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The step's id. A step rewritten in place keeps it.",
                        "examples": [
                            "4e8a2c6d-7b1f-4d93-a5c0-8f2e1b7d6c54"
                        ]
                    },
                    "position": {
                        "type": "integer",
                        "description": "The step's place, contiguous from 1.",
                        "examples": [
                            1
                        ]
                    },
                    "delay_days": {
                        "type": "integer",
                        "description": "Days after the trigger for the first step, 0 to 180 (`0` goes out on the next hourly run); days after the step before for the rest, 1 to 180.",
                        "examples": [
                            3
                        ]
                    },
                    "body": {
                        "type": "string",
                        "description": "The message with its placeholders unfilled: `{name}`, `{project}`, `{coupon}`, `{discount}` and `{link}`.",
                        "examples": [
                            "Hi {name}, your place in {project} is still here whenever you want it back: {link}"
                        ]
                    },
                    "coupon": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The coupon the step carries, present when the relation is loaded; `null` without one.",
                        "examples": [
                            null
                        ],
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The coupon's id."
                            },
                            "code": {
                                "type": "string",
                                "description": "The coupon's code."
                            }
                        },
                        "required": [
                            "id",
                            "code"
                        ]
                    }
                },
                "required": [
                    "id",
                    "position",
                    "delay_days",
                    "body"
                ],
                "title": "SequenceStepResource"
            },
            "SequenceTrigger": {
                "type": "string",
                "description": "What enrols a member in a sequence. Four moments, each with its own listener or sweep: a membership that ended (the churn listener), a lead that arrived (the member service's event), a checkout that stalled (the hourly ledger sweep) and a trial that will end unpaid (the hourly trial sweep). The column is an `enum()` declared whole, so the three Lead nurture triggers were on it before anything fired them; `isAvailable()` is what the surfaces and the service ask before a sequence may be built on a trigger, and it answers yes for all four since Lead nurture.\n",
                "enum": [
                    "churned",
                    "lead",
                    "stalled_checkout",
                    "trial_ending"
                ],
                "title": "SequenceTrigger"
            },
            "SeriesLegSettlement": {
                "type": "string",
                "description": "What cancelling a date does to the season-ticket holders who hold it. A single-date holder is always moved to the plan's next date on sale, because their purchase was that one date. A season-ticket holder bought a slate, so the creator decides per cancellation whether the date is replaced, which keeps their season at the same length, or dropped, which leaves the rest of the season standing and states what the date was worth. A weekly season always has a next date on sale, so without the choice its holders could never be dropped: a day with no event handed them a free date the following week while the single-date holders rightly rolled forward.\n",
                "enum": [
                    "substitute",
                    "drop"
                ],
                "title": "SeriesLegSettlement"
            },
            "SeriesRuleKind": {
                "type": "string",
                "description": "How an auto-include rule decides which dates to pull into a series. Rules exist because a weekly pass plan materialises its windows on a rolling horizon: a creator selling \"every Sunday until December\" would otherwise have to come back and hand-pick each new date as it appears, on a series people have already bought.\n| |\n|---|\n| `date_range` <br/> Every window of the source plan that starts between two dates. |\n| `next_n` <br/> The next N windows of the source plan, whenever they fall. |",
                "enum": [
                    "date_range",
                    "next_n"
                ],
                "title": "SeriesRuleKind"
            },
            "SmartLinkDestination": {
                "type": "string",
                "description": "Where a Smart Link sends the person who follows it. The destination decides the redirect and the bot payload: the portal's plan list, the checkout of one plan, or a conversation with the project's bot. The click and the attribution are recorded the same way whichever it is, so a creator can move a link between destinations without losing its figures.\n",
                "enum": [
                    "portal",
                    "plan",
                    "bot"
                ],
                "title": "SmartLinkDestination"
            },
            "SmartLinkFunnelResource": {
                "type": "object",
                "description": "One row of the Smart Links funnel: the link's lifetime clicks, the members it brought, those who started a purchase, those who paid, and everything those members ever paid, per currency and restated in US dollars. The Direct row has no link and counts the members no link brought, so the rows add up to the project's totals.",
                "properties": {
                    "link_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The link, or null on the Direct row."
                    },
                    "name": {
                        "type": "string",
                        "description": "The link's name, or `Direct`."
                    },
                    "slug": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The link's slug, or null on the Direct row."
                    },
                    "archived": {
                        "type": "boolean",
                        "description": "Whether the link has been archived; false on the Direct row."
                    },
                    "clicks": {
                        "type": "integer",
                        "description": "Lifetime clicks on the web address; 0 on the Direct row, which has no address."
                    },
                    "leads": {
                        "type": "integer",
                        "description": "Members credited to the link: everyone who signed in through it, whether or not they bought."
                    },
                    "checkouts": {
                        "type": "integer",
                        "description": "Those members who started at least one purchase, in any state."
                    },
                    "paid": {
                        "type": "integer",
                        "description": "Those members who made at least one successful payment."
                    },
                    "conversion_rate": {
                        "type": "number",
                        "description": "Paid members per hundred clicks, as a decimal; 0 when there were no clicks."
                    },
                    "revenue": {
                        "type": "object",
                        "description": "Everything those members ever paid, lifetime.",
                        "properties": {
                            "usd": {
                                "type": "string",
                                "description": "The total restated in US dollars at the current rates, a decimal string with two places."
                            },
                            "by_currency": {
                                "type": "array",
                                "description": "The same total per currency, as it was paid.",
                                "items": {
                                    "type": "object",
                                    "properties": {
                                        "currency_id": {
                                            "type": "string",
                                            "description": "The currency."
                                        },
                                        "currency": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "description": "Its ISO 4217 code, when known."
                                        },
                                        "amount": {
                                            "type": "string",
                                            "description": "The amount in that currency, a decimal string with two places."
                                        }
                                    },
                                    "required": [
                                        "currency_id",
                                        "currency",
                                        "amount"
                                    ]
                                }
                            }
                        },
                        "required": [
                            "usd",
                            "by_currency"
                        ]
                    }
                },
                "required": [
                    "link_id",
                    "name",
                    "slug",
                    "archived",
                    "clicks",
                    "leads",
                    "checkouts",
                    "paid",
                    "conversion_rate",
                    "revenue"
                ],
                "title": "SmartLinkFunnelResource"
            },
            "SmartLinkResource": {
                "type": "object",
                "description": "A Smart Link: a tracked address a creator hands out per channel (a video description, a bio, a flyer), with where it sends people, the three addresses to share and its lifetime clicks. Every member who signs in within the attribution window of clicking it is credited to the link.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The link's id.",
                        "examples": [
                            "1e2a4c6b-3d5f-4a7b-9c1d-2e3f4a5b6c7d"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the link belongs to; slugs are unique within a project, not across projects.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "name": {
                        "type": "string",
                        "description": "A creator-facing label, never shown to visitors.",
                        "examples": [
                            "YouTube description"
                        ]
                    },
                    "slug": {
                        "type": "string",
                        "description": "The address segment after `/go/`: 2 to 32 lowercase letters, digits and hyphens. Renaming it changes the web address; the code and the bot link stay.",
                        "examples": [
                            "youtube"
                        ]
                    },
                    "code": {
                        "type": "string",
                        "description": "The stable seven-character code the bot link and the attribution cookie carry. Never changes, so a printed QR and a shared bot link keep working after a rename.",
                        "examples": [
                            "TUBE234"
                        ]
                    },
                    "destination": {
                        "type": "object",
                        "description": "Where the link sends people.",
                        "properties": {
                            "type": {
                                "type": "string",
                                "description": "`portal` (the portal home), `plan` (the checkout of one plan) or `bot` (the project's bot, the portal home when no bot is connected).",
                                "enum": [
                                    "portal",
                                    "plan",
                                    "bot"
                                ],
                                "examples": [
                                    "plan"
                                ]
                            },
                            "plan_id": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The plan a `plan` destination opens; null otherwise.",
                                "examples": [
                                    "0c9d8e7f-6a5b-4c3d-8e2f-1a2b3c4d5e6f"
                                ]
                            },
                            "plan_name": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "That plan's name, present when the relation is loaded.",
                                "examples": [
                                    "Premium"
                                ]
                            }
                        },
                        "required": [
                            "type",
                            "plan_id"
                        ]
                    },
                    "urls": {
                        "type": "object",
                        "description": "The addresses to share, each crediting this link.",
                        "properties": {
                            "web": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The `/go/` address on the portal host. Share it anywhere; a visitor is counted once per hour and remembered for the attribution window.",
                                "examples": [
                                    "https://my.subscriby.net/research-premium/go/youtube"
                                ]
                            },
                            "bot": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The project bot's deep link carrying `via_<code>`; null when the project runs no bot that hands out start links.",
                                "examples": [
                                    "https://t.me/ResearchPremiumBot?start=via_TUBE234"
                                ]
                            },
                            "embed": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The plan-cards page to frame on the creator's own website, with the code in `via`; every card opens the portal in the top window through this link.",
                                "examples": [
                                    "https://my.subscriby.net/research-premium/embed/plans?via=TUBE234"
                                ]
                            }
                        },
                        "required": [
                            "web",
                            "bot",
                            "embed"
                        ]
                    },
                    "state": {
                        "type": "string",
                        "description": "`live` (counts and credits), `expired` (past `expires_at`: the address still lands on the portal home, nothing is counted) or `archived` (put out of use by the creator; the figures stay).",
                        "enum": [
                            "expired",
                            "live",
                            "archived"
                        ],
                        "examples": [
                            "live"
                        ]
                    },
                    "expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the link stops counting, ISO 8601; null for never.",
                        "examples": [
                            null
                        ]
                    },
                    "archived_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the creator archived it, ISO 8601; null while in use.",
                        "examples": [
                            null
                        ]
                    },
                    "clicks": {
                        "type": "object",
                        "description": "Lifetime clicks on the web address, one per visitor address per hour.",
                        "properties": {
                            "total": {
                                "type": "integer",
                                "description": "The count.",
                                "examples": [
                                    42
                                ]
                            },
                            "last_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "When the address was last followed, ISO 8601; null when never.",
                                "examples": [
                                    "2026-10-10T08:00:00+00:00"
                                ]
                            }
                        },
                        "required": [
                            "total",
                            "last_at"
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the link was created, ISO 8601.",
                        "examples": [
                            "2026-10-01T09:00:00+00:00"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it last changed, ISO 8601.",
                        "examples": [
                            "2026-10-10T08:00:00+00:00"
                        ]
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "name",
                    "slug",
                    "code",
                    "destination",
                    "state",
                    "expires_at",
                    "archived_at",
                    "clicks",
                    "created_at",
                    "updated_at"
                ],
                "title": "SmartLinkResource"
            },
            "StartCopilotCreditPackRequest": {
                "type": "object",
                "description": "Validates POST /api/v1/me/copilot-credits/packs: which pack to buy.\n\nOnly the pack is named here. Whether it is on sale in this environment is\nthe service's to say, because that depends on a Stripe price id the\nrequest cannot see, and the refusal is the same 422 either way.",
                "properties": {
                    "pack": {
                        "description": "The pack to buy: `starter` ($10), `regular` ($25, +$2.50 free), `plus` ($50, +$7.50 free) or `max` ($100, +$15 free). `GET /v1/me/copilot-credits` lists the ones on sale.",
                        "$ref": "#/components/schemas/CopilotCreditPack"
                    }
                },
                "required": [
                    "pack"
                ],
                "title": "StartCopilotCreditPackRequest"
            },
            "StoreBroadcastRequest": {
                "type": "object",
                "description": "A message and the segment of the project's members it goes to.",
                "properties": {
                    "message": {
                        "type": "string",
                        "description": "The message body, 1 to 4,096 characters, in the HTML subset the delivering connector accepts. Unknown tags are stripped rather than escaped, because the platform rejects a whole message that holds one.",
                        "minLength": 1,
                        "maxLength": 4096
                    },
                    "audience": {
                        "description": "The segment to address: `all` (the default), `customer`, `trialing`, `lead`, `churned`, `expiring_soon`, `cancelled_still_active`, `paused`, `trialing_cardless`, `all_pass_holders`, `all_pass_holders_not_in_queue`, `pass_holders` or `pass_holders_not_in_queue`.",
                        "$ref": "#/components/schemas/BroadcastAudience"
                    },
                    "pass_window_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uuid",
                        "description": "The access window for `pass_holders` and `pass_holders_not_in_queue`; required by those two, ignored by every other segment."
                    },
                    "plan_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uuid",
                        "description": "Narrow the segment to members whose subscription is on this plan; it composes with `audience` rather than replacing it. Refused, not ignored, for `lead` and the pass segments."
                    },
                    "expiring_within_days": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The horizon `expiring_soon` counts within, 1 to 90; defaults to 7. Read by no other segment.",
                        "minimum": 1,
                        "maximum": 90
                    }
                },
                "required": [
                    "message"
                ],
                "title": "StoreBroadcastRequest"
            },
            "StoreCouponRequest": {
                "type": "object",
                "description": "A coupon to create: the code, what comes off, how often it may be used and when.",
                "properties": {
                    "code": {
                        "type": "string",
                        "description": "The code subscribers type, 3 to 64 letters, numbers and dashes. Stored and matched in upper case, and uppercased before the uniqueness check: `blackfriday` when `BLACKFRIDAY` exists in the project is refused, not a second coupon. Two projects may both hold the same code.",
                        "pattern": "^[A-Za-z0-9-]+$",
                        "minLength": 3,
                        "maxLength": 64
                    },
                    "name": {
                        "type": "string",
                        "description": "A creator-facing label, 3 to 255 characters, never shown to subscribers.",
                        "minLength": 3,
                        "maxLength": 255
                    },
                    "discount_type": {
                        "description": "`percentage` or `fixed`.",
                        "$ref": "#/components/schemas/CouponDiscountType"
                    },
                    "discount_value": {
                        "type": "number",
                        "description": "Greater than 0; at most 100 when `discount_type` is `percentage`."
                    },
                    "currency_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Required when `discount_type` is `fixed`, and it must match the currency of the plans the coupon applies to. Refused as meaningless on a percentage coupon."
                    },
                    "duration": {
                        "type": "string",
                        "description": "Accepted for forward compatibility but only `once` is honoured: first-payment discounts are the only kind that exist today.",
                        "enum": [
                            "once"
                        ]
                    },
                    "max_redemptions": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The total cap across everyone, 1 to 1,000,000. Omit or send null for unlimited.",
                        "minimum": 1,
                        "maximum": 1000000
                    },
                    "max_redemptions_per_user": {
                        "type": "integer",
                        "description": "How many times one member may redeem the code, 1 to 1,000. Defaults to 1.",
                        "minimum": 1,
                        "maximum": 1000
                    },
                    "minimum_amount": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "The order floor, in the plan's own currency; greater than 0."
                    },
                    "starts_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When redemption opens, ISO 8601. Omit for immediately."
                    },
                    "expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When redemption closes, ISO 8601; must be after `starts_at`. Omit for never."
                    },
                    "active": {
                        "type": "boolean",
                        "description": "Whether the code can be redeemed from the start. Defaults to true."
                    },
                    "plan_ids": {
                        "type": "array",
                        "description": "Restrict the code to these plans of the project, at most 200. Omit or send `[]` for every plan, including plans added later.",
                        "items": {
                            "type": "string",
                            "description": "A plan id of this project."
                        },
                        "maxItems": 200
                    }
                },
                "required": [
                    "code",
                    "name",
                    "discount_type",
                    "discount_value"
                ],
                "title": "StoreCouponRequest"
            },
            "StoreGroupRequest": {
                "type": "object",
                "description": "A group's team, code, name and permissions. On create `team_id`, `code` and `name` are required; on update `team_id` and `code` are prohibited (a group is neither moved nor renamed by code) and `name` and `permissions` are optional. Membership is not set here but with the members endpoint.",
                "properties": {
                    "team_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The team to create the group in; the caller must belong to it, and a team outside their account answers 404. Prohibited on update: a group cannot be moved between teams."
                    },
                    "code": {
                        "type": "string",
                        "description": "The machine name, up to 255 letters, numbers, dashes and underscores, unique within the team and immutable afterwards because permissions are addressed by it. Prohibited on update.",
                        "maxLength": 255
                    },
                    "name": {
                        "type": "string",
                        "description": "The display name, up to 255 characters.",
                        "maxLength": 255
                    },
                    "permissions": {
                        "type": "array",
                        "description": "The permission codes the group grants. Sending it sets the group's permissions to exactly this list; omit the key to leave the existing set untouched. Defaults to none on create.",
                        "items": {
                            "type": "string",
                            "description": "A permission code, as `/abilities.json` lists them; an unknown code is refused.",
                            "enum": [
                                "project:view-any",
                                "project:view",
                                "project:create",
                                "project:update",
                                "project:delete",
                                "project-payment-method:view-any",
                                "project-payment-method:view",
                                "project-payment-method:create",
                                "project-payment-method:update",
                                "project-payment-method:delete",
                                "project-resource:view-any",
                                "project-resource:view",
                                "project-resource:create",
                                "project-resource:update",
                                "project-resource:delete",
                                "project-access-code:view-any",
                                "project-access-code:view",
                                "project-access-code:create",
                                "project-access-code:update",
                                "project-access-code:delete",
                                "project-coupon:view-any",
                                "project-coupon:view",
                                "project-coupon:create",
                                "project-coupon:update",
                                "project-coupon:delete",
                                "project-subscription:view-any",
                                "project-subscription:view",
                                "project-subscription:create",
                                "project-subscription:update",
                                "project-subscription:delete",
                                "project-subscription-plan:view-any",
                                "project-subscription-plan:view",
                                "project-subscription-plan:create",
                                "project-subscription-plan:update",
                                "project-subscription-plan:delete",
                                "project-user:view-any",
                                "project-user:view",
                                "project-user:create",
                                "project-user:update",
                                "project-user:delete",
                                "project-recovery:view-any",
                                "project-recovery:view",
                                "project-recovery:create",
                                "project-recovery:update",
                                "project-recovery:delete",
                                "project-connector:view-any",
                                "project-connector:view",
                                "project-connector:create",
                                "project-connector:update",
                                "project-connector:delete",
                                "project-referral:view-any",
                                "project-referral:view",
                                "project-referral:create",
                                "project-referral:update",
                                "project-referral:delete",
                                "project-link:view-any",
                                "project-link:view",
                                "project-link:create",
                                "project-link:update",
                                "project-link:delete",
                                "project-sequence:view-any",
                                "project-sequence:view",
                                "project-sequence:create",
                                "project-sequence:update",
                                "project-sequence:delete",
                                "project-knowledge:view-any",
                                "project-knowledge:view",
                                "project-knowledge:create",
                                "project-knowledge:update",
                                "project-knowledge:delete",
                                "support-conversation:view-any",
                                "support-conversation:view",
                                "support-conversation:create",
                                "support-conversation:update",
                                "support-conversation:delete",
                                "team-member:view-any",
                                "team-member:view",
                                "team-member:invite",
                                "team-member:remove",
                                "team-member:update-role",
                                "copilot:use"
                            ]
                        }
                    }
                },
                "required": [
                    "team_id",
                    "code",
                    "name"
                ],
                "title": "StoreGroupRequest"
            },
            "StoreKnowledgeEntryRequest": {
                "type": "object",
                "description": "A new Knowledge entry: a question with its answer, or a document sent as text, and who may be answered from it.",
                "properties": {
                    "kind": {
                        "description": "`question` or `document`. A question is worded the way a member asks it and answered the way you would; a document is a plain-text or Markdown guide sent in `body`. Fixed once the entry exists.",
                        "$ref": "#/components/schemas/KnowledgeEntryKind"
                    },
                    "title": {
                        "type": "string",
                        "description": "The question, or the document's name, 2 to 160 characters; written at the head of every passage so one read on its own still says where it came from.",
                        "minLength": 2,
                        "maxLength": 160
                    },
                    "body": {
                        "type": "string",
                        "description": "The answer, or the document's text, 2 to 50,000 characters. The Copilot quotes from here and never invents a fact; a Markdown document keeps its headings.",
                        "minLength": 2,
                        "maxLength": 50000
                    },
                    "audience": {
                        "description": "`members` (the default: members may be answered from it, and the team too) or `team` (the creator's own surfaces alone).",
                        "$ref": "#/components/schemas/KnowledgeAudience"
                    }
                },
                "required": [
                    "kind",
                    "title",
                    "body"
                ],
                "title": "StoreKnowledgeEntryRequest"
            },
            "StorePassWindowRequest": {
                "type": "object",
                "description": "A window to place by hand on a time-limited pass plan: when it starts and how long it lasts.",
                "properties": {
                    "starts_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When access opens, ISO 8601. **A value with no offset is read as wall-clock time in the plan's `timezone`**, exactly as the dashboard authors it; a value with an offset or `Z` is the instant it names. Must be in the future, judged in the plan's own zone."
                    },
                    "duration_minutes": {
                        "type": "integer",
                        "description": "How long the window lasts, a whole number of minutes, at least 1. The plan's configured floor and ceiling apply: 5 minutes and 30 days by default.",
                        "minimum": 1
                    }
                },
                "required": [
                    "starts_at",
                    "duration_minutes"
                ],
                "title": "StorePassWindowRequest"
            },
            "StorePlanRequest": {
                "type": "object",
                "description": "A plan to create: `kind` plus the one block it names, in the shape a plan is read back in.",
                "properties": {
                    "kind": {
                        "description": "`subscription`, `pass` or `pass_series`; names the one block the payload carries. Required on create. Omit on an update to keep the plan's current kind.\n| |\n|---|\n| `subscription` <br/> Access starts at payment and runs on a billing cycle. |\n| `pass` <br/> One purchase buys one of the plan's own scheduled access windows. |\n| `pass_series` <br/> One purchase buys a curated slate of *other* plans' access windows. |",
                        "$ref": "#/components/schemas/PlanKind"
                    },
                    "name": {
                        "type": "string",
                        "description": "The name buyers see, 5 to 255 characters, unique within the project without regard to case or surrounding spaces. Required on create.",
                        "minLength": 5,
                        "maxLength": 255
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The pitch under the name, up to 1,000 characters. HTML is filtered to a safe subset before it is stored.",
                        "maxLength": 1000
                    },
                    "currency_id": {
                        "type": "string",
                        "description": "The id of a currency that at least one of the project's active payment methods can charge. Required on create."
                    },
                    "price": {
                        "type": "number",
                        "description": "What one purchase costs: at least the $1.00 USD equivalent in `currency_id` at the current rate, or exactly `0` for a free plan, which only a Starter or Growth account may put on sale. Required on create.",
                        "minimum": 0
                    },
                    "active": {
                        "type": "boolean",
                        "description": "Whether the plan is on sale. Defaults to true on create; prefer the publish and unpublish endpoints to change it later."
                    },
                    "sales_cap": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Pause the plan after this many purchases, 1 to 100,000; null for no limit. Changing it restarts `sales_cap_sold` at 0.",
                        "minimum": 1,
                        "maximum": 100000
                    },
                    "eligibility": {
                        "type": "object",
                        "description": "Who may buy. At most one of the first three may be true, counting what the plan already holds on an update.",
                        "properties": {
                            "newcomers_only": {
                                "type": "boolean",
                                "description": "Only members who never held a subscription on the project."
                            },
                            "customers_only": {
                                "type": "boolean",
                                "description": "Only members who currently hold one."
                            },
                            "churned_only": {
                                "type": "boolean",
                                "description": "Only members who held one and let it lapse."
                            },
                            "single_use": {
                                "type": "boolean",
                                "description": "Each member may buy the plan once."
                            },
                            "access_codes_only": {
                                "type": "boolean",
                                "description": "The plan cannot be bought, only granted by redeeming an access code."
                            }
                        }
                    },
                    "resources": {
                        "type": "array",
                        "description": "Ids of the project's resources the plan grants: at least one, required on create, except on `kind: pass_series`, where it is optional and names a lounge open for the whole span. Omit on an update to keep the existing links.",
                        "items": {
                            "type": "string",
                            "description": "A resource id."
                        },
                        "minItems": 1
                    },
                    "billing": {
                        "type": "object",
                        "description": "Cycle, trial and renewal. Send it on `kind: subscription` only; on any other kind it is refused.",
                        "properties": {
                            "billing_cycle": {
                                "description": "`day`, `week`, `month`, `year` or `lifetime`. Required on create.",
                                "$ref": "#/components/schemas/SubscriptionBillingCycle"
                            },
                            "billing_cycle_count": {
                                "type": "integer",
                                "description": "How many cycles one period spans, 1 to 99; must be 1 when the cycle is `lifetime`. Required on create.",
                                "minimum": 1,
                                "maximum": 99
                            },
                            "recurring": {
                                "type": "boolean",
                                "description": "Whether the subscription renews itself. Refused as true when the currency is a crypto or platform currency."
                            },
                            "disabled_renewal": {
                                "type": "boolean",
                                "description": "Charge once, then lapse at the end of the period instead of renewing."
                            },
                            "trial_days": {
                                "type": "integer",
                                "description": "Free days before the first charge, 0 to 365.",
                                "minimum": 0,
                                "maximum": 365
                            },
                            "trial_cardless": {
                                "type": "boolean",
                                "description": "Whether the trial starts without a payment method on file."
                            },
                            "trial_type": {
                                "description": "Whose trial rule applies: `project` uses the project's trial settings, `plan` this plan's own.",
                                "$ref": "#/components/schemas/TrialModeType"
                            }
                        },
                        "required": [
                            "billing_cycle",
                            "billing_cycle_count"
                        ]
                    },
                    "pass": {
                        "type": "object",
                        "description": "The plan's own dated schedule. Send it on `kind: pass` only; on any other kind it is refused.",
                        "properties": {
                            "timezone": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The IANA zone the schedule is authored in. Legacy names are resolved, so `Asia/Calcutta` is stored as `Asia/Kolkata`. Required on create.",
                                "enum": [
                                    "GMT",
                                    "UTC",
                                    "Africa/Abidjan",
                                    "Africa/Accra",
                                    "Africa/Bamako",
                                    "Africa/Banjul",
                                    "Africa/Bissau",
                                    "Africa/Casablanca",
                                    "Africa/Conakry",
                                    "Africa/Dakar",
                                    "Africa/El_Aaiun",
                                    "Africa/Freetown",
                                    "Africa/Lome",
                                    "Africa/Monrovia",
                                    "Africa/Nouakchott",
                                    "Africa/Ouagadougou",
                                    "Africa/Sao_Tome",
                                    "Africa/Algiers",
                                    "Africa/Bangui",
                                    "Africa/Brazzaville",
                                    "Africa/Ceuta",
                                    "Africa/Douala",
                                    "Africa/Kinshasa",
                                    "Africa/Lagos",
                                    "Africa/Libreville",
                                    "Africa/Luanda",
                                    "Africa/Malabo",
                                    "Africa/Ndjamena",
                                    "Africa/Niamey",
                                    "Africa/Porto-Novo",
                                    "Africa/Tunis",
                                    "Africa/Blantyre",
                                    "Africa/Bujumbura",
                                    "Africa/Cairo",
                                    "Africa/Gaborone",
                                    "Africa/Harare",
                                    "Africa/Johannesburg",
                                    "Africa/Juba",
                                    "Africa/Khartoum",
                                    "Africa/Kigali",
                                    "Africa/Lubumbashi",
                                    "Africa/Lusaka",
                                    "Africa/Maputo",
                                    "Africa/Maseru",
                                    "Africa/Mbabane",
                                    "Africa/Tripoli",
                                    "Africa/Windhoek",
                                    "Africa/Addis_Ababa",
                                    "Africa/Asmara",
                                    "Africa/Dar_es_Salaam",
                                    "Africa/Djibouti",
                                    "Africa/Kampala",
                                    "Africa/Mogadishu",
                                    "Africa/Nairobi",
                                    "America/Adak",
                                    "America/Anchorage",
                                    "America/Juneau",
                                    "America/Metlakatla",
                                    "America/Nome",
                                    "America/Sitka",
                                    "America/Yakutat",
                                    "America/Los_Angeles",
                                    "America/Tijuana",
                                    "America/Boise",
                                    "America/Cambridge_Bay",
                                    "America/Ciudad_Juarez",
                                    "America/Creston",
                                    "America/Dawson",
                                    "America/Dawson_Creek",
                                    "America/Denver",
                                    "America/Fort_Nelson",
                                    "America/Hermosillo",
                                    "America/Mazatlan",
                                    "America/Phoenix",
                                    "America/Vancouver",
                                    "America/Whitehorse",
                                    "America/Bahia_Banderas",
                                    "America/Belize",
                                    "America/Chicago",
                                    "America/Chihuahua",
                                    "America/Costa_Rica",
                                    "America/Edmonton",
                                    "America/El_Salvador",
                                    "America/Guatemala",
                                    "America/Indiana/Knox",
                                    "America/Indiana/Tell_City",
                                    "America/Inuvik",
                                    "America/Managua",
                                    "America/Matamoros",
                                    "America/Menominee",
                                    "America/Merida",
                                    "America/Mexico_City",
                                    "America/Monterrey",
                                    "America/North_Dakota/Beulah",
                                    "America/North_Dakota/Center",
                                    "America/North_Dakota/New_Salem",
                                    "America/Ojinaga",
                                    "America/Rankin_Inlet",
                                    "America/Regina",
                                    "America/Resolute",
                                    "America/Swift_Current",
                                    "America/Tegucigalpa",
                                    "America/Atikokan",
                                    "America/Bogota",
                                    "America/Cancun",
                                    "America/Cayman",
                                    "America/Detroit",
                                    "America/Eirunepe",
                                    "America/Grand_Turk",
                                    "America/Guayaquil",
                                    "America/Havana",
                                    "America/Indiana/Indianapolis",
                                    "America/Indiana/Marengo",
                                    "America/Indiana/Petersburg",
                                    "America/Indiana/Vevay",
                                    "America/Indiana/Vincennes",
                                    "America/Indiana/Winamac",
                                    "America/Iqaluit",
                                    "America/Jamaica",
                                    "America/Kentucky/Louisville",
                                    "America/Kentucky/Monticello",
                                    "America/Lima",
                                    "America/Nassau",
                                    "America/New_York",
                                    "America/Panama",
                                    "America/Port-au-Prince",
                                    "America/Rio_Branco",
                                    "America/Toronto",
                                    "America/Winnipeg",
                                    "America/Anguilla",
                                    "America/Antigua",
                                    "America/Aruba",
                                    "America/Barbados",
                                    "America/Blanc-Sablon",
                                    "America/Boa_Vista",
                                    "America/Campo_Grande",
                                    "America/Caracas",
                                    "America/Cuiaba",
                                    "America/Curacao",
                                    "America/Dominica",
                                    "America/Glace_Bay",
                                    "America/Goose_Bay",
                                    "America/Grenada",
                                    "America/Guadeloupe",
                                    "America/Guyana",
                                    "America/Halifax",
                                    "America/Kralendijk",
                                    "America/La_Paz",
                                    "America/Lower_Princes",
                                    "America/Manaus",
                                    "America/Marigot",
                                    "America/Martinique",
                                    "America/Moncton",
                                    "America/Montserrat",
                                    "America/Port_of_Spain",
                                    "America/Porto_Velho",
                                    "America/Puerto_Rico",
                                    "America/Santo_Domingo",
                                    "America/St_Barthelemy",
                                    "America/St_Kitts",
                                    "America/St_Lucia",
                                    "America/St_Thomas",
                                    "America/St_Vincent",
                                    "America/Thule",
                                    "America/Tortola",
                                    "America/St_Johns",
                                    "America/Araguaina",
                                    "America/Argentina/Buenos_Aires",
                                    "America/Argentina/Catamarca",
                                    "America/Argentina/Cordoba",
                                    "America/Argentina/Jujuy",
                                    "America/Argentina/La_Rioja",
                                    "America/Argentina/Mendoza",
                                    "America/Argentina/Rio_Gallegos",
                                    "America/Argentina/Salta",
                                    "America/Argentina/San_Juan",
                                    "America/Argentina/San_Luis",
                                    "America/Argentina/Tucuman",
                                    "America/Argentina/Ushuaia",
                                    "America/Asuncion",
                                    "America/Bahia",
                                    "America/Belem",
                                    "America/Cayenne",
                                    "America/Coyhaique",
                                    "America/Fortaleza",
                                    "America/Maceio",
                                    "America/Miquelon",
                                    "America/Montevideo",
                                    "America/Paramaribo",
                                    "America/Punta_Arenas",
                                    "America/Recife",
                                    "America/Santarem",
                                    "America/Santiago",
                                    "America/Sao_Paulo",
                                    "America/Noronha",
                                    "America/Nuuk",
                                    "America/Scoresbysund",
                                    "America/Danmarkshavn",
                                    "Antarctica/Palmer",
                                    "Antarctica/Rothera",
                                    "Antarctica/Troll",
                                    "Antarctica/Syowa",
                                    "Antarctica/Mawson",
                                    "Antarctica/Vostok",
                                    "Antarctica/Davis",
                                    "Antarctica/Casey",
                                    "Antarctica/DumontDUrville",
                                    "Antarctica/Macquarie",
                                    "Antarctica/McMurdo",
                                    "Arctic/Longyearbyen",
                                    "Asia/Beirut",
                                    "Asia/Famagusta",
                                    "Asia/Gaza",
                                    "Asia/Hebron",
                                    "Asia/Jerusalem",
                                    "Asia/Nicosia",
                                    "Asia/Aden",
                                    "Asia/Amman",
                                    "Asia/Baghdad",
                                    "Asia/Bahrain",
                                    "Asia/Damascus",
                                    "Asia/Kuwait",
                                    "Asia/Qatar",
                                    "Asia/Riyadh",
                                    "Asia/Tehran",
                                    "Asia/Baku",
                                    "Asia/Dubai",
                                    "Asia/Muscat",
                                    "Asia/Tbilisi",
                                    "Asia/Yerevan",
                                    "Asia/Kabul",
                                    "Asia/Almaty",
                                    "Asia/Aqtau",
                                    "Asia/Aqtobe",
                                    "Asia/Ashgabat",
                                    "Asia/Atyrau",
                                    "Asia/Dushanbe",
                                    "Asia/Karachi",
                                    "Asia/Oral",
                                    "Asia/Qostanay",
                                    "Asia/Qyzylorda",
                                    "Asia/Samarkand",
                                    "Asia/Tashkent",
                                    "Asia/Yekaterinburg",
                                    "Asia/Colombo",
                                    "Asia/Kolkata",
                                    "Asia/Kathmandu",
                                    "Asia/Bishkek",
                                    "Asia/Dhaka",
                                    "Asia/Omsk",
                                    "Asia/Thimphu",
                                    "Asia/Urumqi",
                                    "Asia/Yangon",
                                    "Asia/Bangkok",
                                    "Asia/Barnaul",
                                    "Asia/Ho_Chi_Minh",
                                    "Asia/Hovd",
                                    "Asia/Jakarta",
                                    "Asia/Krasnoyarsk",
                                    "Asia/Novokuznetsk",
                                    "Asia/Novosibirsk",
                                    "Asia/Phnom_Penh",
                                    "Asia/Pontianak",
                                    "Asia/Tomsk",
                                    "Asia/Vientiane",
                                    "Asia/Brunei",
                                    "Asia/Hong_Kong",
                                    "Asia/Irkutsk",
                                    "Asia/Kuala_Lumpur",
                                    "Asia/Kuching",
                                    "Asia/Macau",
                                    "Asia/Makassar",
                                    "Asia/Manila",
                                    "Asia/Shanghai",
                                    "Asia/Singapore",
                                    "Asia/Taipei",
                                    "Asia/Ulaanbaatar",
                                    "Asia/Chita",
                                    "Asia/Dili",
                                    "Asia/Jayapura",
                                    "Asia/Khandyga",
                                    "Asia/Pyongyang",
                                    "Asia/Seoul",
                                    "Asia/Tokyo",
                                    "Asia/Yakutsk",
                                    "Asia/Ust-Nera",
                                    "Asia/Vladivostok",
                                    "Asia/Magadan",
                                    "Asia/Sakhalin",
                                    "Asia/Srednekolymsk",
                                    "Asia/Anadyr",
                                    "Asia/Kamchatka",
                                    "Atlantic/Bermuda",
                                    "Atlantic/Stanley",
                                    "Atlantic/South_Georgia",
                                    "Atlantic/Azores",
                                    "Atlantic/Cape_Verde",
                                    "Atlantic/Canary",
                                    "Atlantic/Faroe",
                                    "Atlantic/Madeira",
                                    "Atlantic/Reykjavik",
                                    "Atlantic/St_Helena",
                                    "Australia/Perth",
                                    "Australia/Eucla",
                                    "Australia/Darwin",
                                    "Australia/Brisbane",
                                    "Australia/Lindeman",
                                    "Australia/Adelaide",
                                    "Australia/Broken_Hill",
                                    "Australia/Hobart",
                                    "Australia/Lord_Howe",
                                    "Australia/Melbourne",
                                    "Australia/Sydney",
                                    "Europe/Dublin",
                                    "Europe/Guernsey",
                                    "Europe/Isle_of_Man",
                                    "Europe/Jersey",
                                    "Europe/Lisbon",
                                    "Europe/London",
                                    "Europe/Amsterdam",
                                    "Europe/Andorra",
                                    "Europe/Belgrade",
                                    "Europe/Berlin",
                                    "Europe/Bratislava",
                                    "Europe/Brussels",
                                    "Europe/Budapest",
                                    "Europe/Busingen",
                                    "Europe/Copenhagen",
                                    "Europe/Gibraltar",
                                    "Europe/Ljubljana",
                                    "Europe/Luxembourg",
                                    "Europe/Madrid",
                                    "Europe/Malta",
                                    "Europe/Monaco",
                                    "Europe/Oslo",
                                    "Europe/Paris",
                                    "Europe/Podgorica",
                                    "Europe/Prague",
                                    "Europe/Rome",
                                    "Europe/San_Marino",
                                    "Europe/Sarajevo",
                                    "Europe/Skopje",
                                    "Europe/Stockholm",
                                    "Europe/Tirane",
                                    "Europe/Vaduz",
                                    "Europe/Vatican",
                                    "Europe/Vienna",
                                    "Europe/Warsaw",
                                    "Europe/Zagreb",
                                    "Europe/Zurich",
                                    "Europe/Athens",
                                    "Europe/Bucharest",
                                    "Europe/Chisinau",
                                    "Europe/Helsinki",
                                    "Europe/Kaliningrad",
                                    "Europe/Kyiv",
                                    "Europe/Mariehamn",
                                    "Europe/Riga",
                                    "Europe/Sofia",
                                    "Europe/Tallinn",
                                    "Europe/Vilnius",
                                    "Europe/Istanbul",
                                    "Europe/Kirov",
                                    "Europe/Minsk",
                                    "Europe/Moscow",
                                    "Europe/Simferopol",
                                    "Europe/Volgograd",
                                    "Europe/Astrakhan",
                                    "Europe/Samara",
                                    "Europe/Saratov",
                                    "Europe/Ulyanovsk",
                                    "Indian/Antananarivo",
                                    "Indian/Comoro",
                                    "Indian/Mayotte",
                                    "Indian/Mahe",
                                    "Indian/Mauritius",
                                    "Indian/Reunion",
                                    "Indian/Kerguelen",
                                    "Indian/Maldives",
                                    "Indian/Chagos",
                                    "Indian/Cocos",
                                    "Indian/Christmas",
                                    "Pacific/Midway",
                                    "Pacific/Niue",
                                    "Pacific/Pago_Pago",
                                    "Pacific/Honolulu",
                                    "Pacific/Rarotonga",
                                    "Pacific/Tahiti",
                                    "Pacific/Marquesas",
                                    "Pacific/Gambier",
                                    "Pacific/Pitcairn",
                                    "Pacific/Galapagos",
                                    "Pacific/Easter",
                                    "Pacific/Palau",
                                    "Pacific/Chuuk",
                                    "Pacific/Guam",
                                    "Pacific/Port_Moresby",
                                    "Pacific/Saipan",
                                    "Pacific/Bougainville",
                                    "Pacific/Efate",
                                    "Pacific/Guadalcanal",
                                    "Pacific/Kosrae",
                                    "Pacific/Noumea",
                                    "Pacific/Pohnpei",
                                    "Pacific/Fiji",
                                    "Pacific/Funafuti",
                                    "Pacific/Kwajalein",
                                    "Pacific/Majuro",
                                    "Pacific/Nauru",
                                    "Pacific/Norfolk",
                                    "Pacific/Tarawa",
                                    "Pacific/Wake",
                                    "Pacific/Wallis",
                                    "Pacific/Apia",
                                    "Pacific/Auckland",
                                    "Pacific/Fakaofo",
                                    "Pacific/Kanton",
                                    "Pacific/Tongatapu",
                                    "Pacific/Chatham",
                                    "Pacific/Kiritimati",
                                    null
                                ]
                            },
                            "schedule_mode": {
                                "description": "`repeating` (the default) generates windows from `slots`; `fixed` takes explicitly dated `windows`.",
                                "anyOf": [
                                    {
                                        "$ref": "#/components/schemas/PassScheduleMode"
                                    },
                                    {
                                        "type": "null"
                                    }
                                ]
                            },
                            "recurrence": {
                                "description": "`daily`, `weekly` or `monthly`. Decides which slot fields apply.",
                                "anyOf": [
                                    {
                                        "$ref": "#/components/schemas/PassRecurrence"
                                    },
                                    {
                                        "type": "null"
                                    }
                                ]
                            },
                            "recurrence_ends_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "format": "date-time",
                                "description": "When window generation stops; omit to keep generating."
                            },
                            "sales_cutoff_minutes": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "Stop sales this many minutes before the moment `sales_cutoff_anchor` names; omit to sell until the window begins. With `before_end` it must be at least 5 and under the shortest slot's `duration_minutes`.",
                                "minimum": 0
                            },
                            "sales_cutoff_anchor": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "`before_start` (the default) or `before_end`. `before_end` is refused when the shortest slot lasts 5 minutes or less. The series anchors `before_first_end` and `before_last_start` are refused on a pass.",
                                "enum": [
                                    "before_start",
                                    "before_end",
                                    null
                                ]
                            },
                            "slots": {
                                "type": "array",
                                "description": "The repeating schedule, at most 60 slots. Sending it replaces the whole schedule and rebuilds unsold future windows; windows a customer has bought keep their times.",
                                "items": {
                                    "type": "object",
                                    "properties": {
                                        "weekday": {
                                            "type": [
                                                "integer",
                                                "null"
                                            ],
                                            "description": "Day of the week, 0 (Sunday) to 6, on a weekly recurrence.",
                                            "minimum": 0,
                                            "maximum": 6
                                        },
                                        "day_of_month": {
                                            "type": [
                                                "integer",
                                                "null"
                                            ],
                                            "description": "Day of the month, 1 to 31, on a monthly recurrence; 29 to 31 skip the months that lack the day.",
                                            "minimum": 1,
                                            "maximum": 31
                                        },
                                        "start_time": {
                                            "type": "string",
                                            "description": "Local wall-clock start in `pass.timezone`, `HH:MM`."
                                        },
                                        "duration_minutes": {
                                            "type": "integer",
                                            "description": "How long the window stays open.",
                                            "minimum": 5,
                                            "maximum": 43200
                                        }
                                    }
                                },
                                "maxItems": 60
                            },
                            "windows": {
                                "type": "array",
                                "description": "Explicitly dated windows for `schedule_mode: fixed`, at most 200 per call. Added to the schedule, never replacing it.",
                                "items": {
                                    "type": "object",
                                    "properties": {
                                        "starts_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "description": "Local wall-clock start in `pass.timezone`."
                                        },
                                        "duration_minutes": {
                                            "type": "integer",
                                            "description": "How long the window stays open.",
                                            "minimum": 5,
                                            "maximum": 43200
                                        }
                                    }
                                },
                                "maxItems": 200
                            }
                        }
                    },
                    "pass_series": {
                        "type": "object",
                        "description": "The season ticket's slate, rules and seats. Send it on `kind: pass_series` only; on any other kind it is refused.",
                        "properties": {
                            "prevent_overlaps": {
                                "type": "boolean",
                                "description": "Refuse a window that clashes with one already on the slate. Defaults to true."
                            },
                            "sales_cutoff_minutes": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "Stop sales this many minutes before the moment `sales_cutoff_anchor` names, measured against the whole season.",
                                "minimum": 0
                            },
                            "sales_cutoff_anchor": {
                                "description": "`before_start` (the default), `before_first_end`, `before_last_start` or `before_end`. `before_first_end` needs `sales_cutoff_minutes` of at least 5, so a buyer arriving late in the opening window is still admitted to it.",
                                "anyOf": [
                                    {
                                        "$ref": "#/components/schemas/PassSalesCutoffAnchor"
                                    },
                                    {
                                        "type": "null"
                                    }
                                ]
                            },
                            "seat_cap": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "How many holders may hold the season at once, at least 1; null for unlimited. Zero is refused: take the plan off sale with unpublish instead.",
                                "minimum": 1
                            },
                            "presale_hours": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "How long the next season is offered to current holders only, 1 to 8760.",
                                "minimum": 1,
                                "maximum": 8760
                            },
                            "successor_plan_id": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Another `kind: pass_series` plan on the same project to offer holders when this one finishes. A series cannot lead to itself."
                            },
                            "window_ids": {
                                "type": "array",
                                "description": "Ids of pass windows on this project to put on the slate, at most 120. A slate needs at least two unless a rule will supply them; with `prevent_overlaps` on, two that run at the same time are refused.",
                                "items": {
                                    "type": "string",
                                    "description": "A pass window id."
                                },
                                "maxItems": 120
                            },
                            "blackout_window_ids": {
                                "type": "array",
                                "description": "Windows a rule matches but you want permanently excluded.",
                                "items": {
                                    "type": "string",
                                    "description": "A pass window id."
                                }
                            },
                            "rules": {
                                "type": "array",
                                "description": "Rules that keep absorbing matching windows into the slate, at most 20. A matching window scheduled later is added and granted to every current holder at no charge.",
                                "items": {
                                    "type": "object",
                                    "properties": {
                                        "source_plan_id": {
                                            "type": "string",
                                            "description": "A `kind: pass` plan on this project to draw windows from."
                                        },
                                        "kind": {
                                            "description": "`date_range` takes every window between `from_at` and `to_at`; `next_n` takes the next `take` windows.\n| |\n|---|\n| `date_range` <br/> Every window of the source plan that starts between two dates. |\n| `next_n` <br/> The next N windows of the source plan, whenever they fall. |",
                                            "$ref": "#/components/schemas/SeriesRuleKind"
                                        },
                                        "from_at": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "format": "date-time",
                                            "description": "The earliest window start a `date_range` rule takes."
                                        },
                                        "to_at": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "format": "date-time",
                                            "description": "The latest window start a `date_range` rule takes."
                                        },
                                        "take": {
                                            "type": [
                                                "integer",
                                                "null"
                                            ],
                                            "description": "How many windows a `next_n` rule takes, 1 to 120; required when `kind` is `next_n`.",
                                            "minimum": 1,
                                            "maximum": 120
                                        }
                                    }
                                },
                                "maxItems": 20
                            }
                        }
                    }
                },
                "required": [
                    "kind",
                    "name",
                    "currency_id",
                    "price",
                    "resources",
                    "billing"
                ],
                "title": "StorePlanRequest"
            },
            "StoreProjectRequest": {
                "type": "object",
                "description": "A new project. Send JSON, or `multipart/form-data` when uploading the banner or photo; the response carries the project's metadata only, and the hosted image URLs appear on a later read once processing has finished.",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "The project's name, 5 to 255 characters.",
                        "minLength": 5,
                        "maxLength": 255
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the project offers, up to 1,000 characters. HTML is filtered to a safe subset before storage.",
                        "maxLength": 1000
                    },
                    "terms": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uri",
                        "description": "The URL of the terms members are asked to accept, `https://` or `http://`, up to 255 characters.",
                        "maxLength": 255
                    },
                    "privacy": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uri",
                        "description": "The URL of the privacy policy members are asked to accept, `https://` or `http://`, up to 255 characters.",
                        "maxLength": 255
                    },
                    "banner": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "binary",
                        "contentMediaType": "application/octet-stream",
                        "description": "The banner image (jpg, jpeg, png, gif, bmp, webp or avif), at most 5 MB, as a `multipart/form-data` upload. Resized, re-encoded and uploaded after the request; read the project again for its URL."
                    },
                    "photo": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "binary",
                        "contentMediaType": "application/octet-stream",
                        "description": "The photo image (jpg, jpeg, png, gif, bmp, webp or avif), at most 5 MB, as a `multipart/form-data` upload. Processed after the request like the banner."
                    },
                    "active": {
                        "type": "boolean",
                        "description": "Whether the project starts live."
                    },
                    "team_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The team to create the project in; must be one the token's owner belongs to. Defaults to the token's scoped team."
                    },
                    "handle": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The portal handle: lowercase letters, digits, dashes and underscores, 5 to 255 characters, unique across every project's current and former handles, on every tier. Omitted, a random handle is assigned, which can be changed later with the old address kept redirecting.",
                        "minLength": 5,
                        "maxLength": 255
                    },
                    "hide_branding": {
                        "type": "boolean",
                        "description": "The **Remove Subscriby Branding** switch: true takes the \"Powered by\" mark off the portal page, its social card and the bot. Off by default on every plan; turning it on needs a tier with the `no_branding` capability (Starter or Growth), `TEAM_TIER_REQUIRED` otherwise."
                    }
                },
                "required": [
                    "name"
                ],
                "title": "StoreProjectRequest"
            },
            "StoreReferralAffiliateRequest": {
                "type": "object",
                "description": "A member to enrol as an affiliate by hand: approved whatever the programme's switches say, and handed their code and links at once.",
                "properties": {
                    "member_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The id of a member of this project, as the members endpoints list them."
                    }
                },
                "required": [
                    "member_id"
                ],
                "title": "StoreReferralAffiliateRequest"
            },
            "StoreReferralPayoutRequest": {
                "type": "object",
                "description": "A payout to record: the affiliate, how much was paid, in which currency, and your own reference and note.",
                "properties": {
                    "affiliate_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The affiliate who was paid, as the referral-affiliates endpoints list them."
                    },
                    "amount": {
                        "type": "number",
                        "description": "What was paid, greater than 0, at most the affiliate's payable balance in that currency."
                    },
                    "currency_id": {
                        "type": "string",
                        "description": "The currency the commissions were earned in; a balance exists per currency."
                    },
                    "reference": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Your own reference, such as a transfer id; at most 120 characters.",
                        "maxLength": 120
                    },
                    "note": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A note for your records; at most 1,000 characters.",
                        "maxLength": 1000
                    }
                },
                "required": [
                    "affiliate_id",
                    "amount",
                    "currency_id"
                ],
                "title": "StoreReferralPayoutRequest"
            },
            "StoreResourceRequest": {
                "type": "object",
                "description": "A new manual perk. The payload names no kind and no place: a place a connector gates is asked for with the link-request endpoint.",
                "properties": {
                    "title": {
                        "type": "string",
                        "description": "The perk's name on plan cards, 5 to 255 characters.",
                        "minLength": 5,
                        "maxLength": 255
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the perk is, up to 1,000 characters. HTML is filtered to a safe subset before storage.",
                        "maxLength": 1000
                    },
                    "active": {
                        "type": "boolean",
                        "description": "Whether plans grant it right away. Defaults to true."
                    }
                },
                "required": [
                    "title"
                ],
                "title": "StoreResourceRequest"
            },
            "StoreRoleRequest": {
                "type": "object",
                "description": "A role's team, code, name, description and permissions. On create `team_id`, `code` and `name` are required; on update `team_id` and `code` are prohibited (a role is neither moved nor renamed by code) and every other field is optional.",
                "properties": {
                    "team_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The team to create the role in; the caller must belong to it, and a team outside their account answers 404. Prohibited on update: a role cannot be moved between teams."
                    },
                    "code": {
                        "type": "string",
                        "description": "The stable identifier permissions are addressed by, up to 255 letters, numbers, dashes and underscores, unique within the team and immutable afterwards: renaming one would detach every assignment that referenced it. Prohibited on update.",
                        "maxLength": 255
                    },
                    "name": {
                        "type": "string",
                        "description": "The display name, up to 255 characters.",
                        "maxLength": 255
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the role is for, up to 255 characters; null clears it.",
                        "maxLength": 255
                    },
                    "permissions": {
                        "type": "array",
                        "description": "The permission codes the role grants, in `entity:action` form. Sending it sets the role's permissions to exactly this list; omit the key to leave the existing set untouched. Omit it on create for a role that grants nothing yet.",
                        "items": {
                            "type": "string",
                            "description": "A permission code from the catalog; an unknown code is refused rather than silently dropped, so a typo fails loudly instead of creating a role that grants less than you think.",
                            "enum": [
                                "project:view-any",
                                "project:view",
                                "project:create",
                                "project:update",
                                "project:delete",
                                "project-payment-method:view-any",
                                "project-payment-method:view",
                                "project-payment-method:create",
                                "project-payment-method:update",
                                "project-payment-method:delete",
                                "project-resource:view-any",
                                "project-resource:view",
                                "project-resource:create",
                                "project-resource:update",
                                "project-resource:delete",
                                "project-access-code:view-any",
                                "project-access-code:view",
                                "project-access-code:create",
                                "project-access-code:update",
                                "project-access-code:delete",
                                "project-coupon:view-any",
                                "project-coupon:view",
                                "project-coupon:create",
                                "project-coupon:update",
                                "project-coupon:delete",
                                "project-subscription:view-any",
                                "project-subscription:view",
                                "project-subscription:create",
                                "project-subscription:update",
                                "project-subscription:delete",
                                "project-subscription-plan:view-any",
                                "project-subscription-plan:view",
                                "project-subscription-plan:create",
                                "project-subscription-plan:update",
                                "project-subscription-plan:delete",
                                "project-user:view-any",
                                "project-user:view",
                                "project-user:create",
                                "project-user:update",
                                "project-user:delete",
                                "project-recovery:view-any",
                                "project-recovery:view",
                                "project-recovery:create",
                                "project-recovery:update",
                                "project-recovery:delete",
                                "project-connector:view-any",
                                "project-connector:view",
                                "project-connector:create",
                                "project-connector:update",
                                "project-connector:delete",
                                "project-referral:view-any",
                                "project-referral:view",
                                "project-referral:create",
                                "project-referral:update",
                                "project-referral:delete",
                                "project-link:view-any",
                                "project-link:view",
                                "project-link:create",
                                "project-link:update",
                                "project-link:delete",
                                "project-sequence:view-any",
                                "project-sequence:view",
                                "project-sequence:create",
                                "project-sequence:update",
                                "project-sequence:delete",
                                "project-knowledge:view-any",
                                "project-knowledge:view",
                                "project-knowledge:create",
                                "project-knowledge:update",
                                "project-knowledge:delete",
                                "support-conversation:view-any",
                                "support-conversation:view",
                                "support-conversation:create",
                                "support-conversation:update",
                                "support-conversation:delete",
                                "team-member:view-any",
                                "team-member:view",
                                "team-member:invite",
                                "team-member:remove",
                                "team-member:update-role",
                                "copilot:use"
                            ]
                        }
                    }
                },
                "required": [
                    "team_id",
                    "code",
                    "name"
                ],
                "title": "StoreRoleRequest"
            },
            "StoreSequenceRequest": {
                "type": "object",
                "description": "A sequence to build: its name, what starts it, whether it runs, and the steps in the order they go out. Needs the Growth plan or the Revenue Recovery Addon.",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "A creator-facing label, 1 to 120 characters; such as `Win-back after churn`.",
                        "minLength": 1,
                        "maxLength": 120
                    },
                    "trigger": {
                        "type": "string",
                        "description": "What enrols a member: `churned` (their last live membership ended; the default), `lead` (they arrived without buying), `stalled_checkout` (a checkout they started stayed open past the project's window) or `trial_ending` (a trial without a card is about to end).",
                        "enum": [
                            "churned",
                            "lead",
                            "stalled_checkout",
                            "trial_ending"
                        ]
                    },
                    "active": {
                        "type": "boolean",
                        "description": "Whether the sequence enrols and sends from the start. Defaults to `true`."
                    },
                    "steps": {
                        "type": "array",
                        "description": "The steps in the order they go out, at most 8. Omit for a sequence with no steps yet, which enrols nobody.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "delay_days": {
                                    "type": "integer",
                                    "description": "Days after the trigger for the first step, 0 to 180 (`0` goes out on the next hourly run); days after the step before for the rest, 1 to 180.",
                                    "minimum": 0,
                                    "maximum": 180
                                },
                                "body": {
                                    "type": "string",
                                    "description": "The message in the creator's words, 1 to 1,000 characters of text, with `{name}`, `{project}`, `{coupon}`, `{discount}` and `{link}` filled per member at send time. Plain text or HTML: bold, italic, underline, strikethrough, code, links and paragraphs are kept, everything else is stripped to its words."
                                },
                                "coupon_id": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "One of this project's coupons to carry with the step, or `null`."
                                }
                            },
                            "required": [
                                "delay_days",
                                "body"
                            ]
                        },
                        "maxItems": 8
                    }
                },
                "required": [
                    "name"
                ],
                "title": "StoreSequenceRequest"
            },
            "StoreSmartLinkRequest": {
                "type": "object",
                "description": "A Smart Link to create: its name, its address segment, where it sends people and, optionally, when it stops counting.",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "A creator-facing label, 2 to 120 characters, never shown to visitors; such as `YouTube description`.",
                        "minLength": 2,
                        "maxLength": 120
                    },
                    "slug": {
                        "type": "string",
                        "description": "The address segment after `/go/`: 2 to 32 letters, digits and hyphens, lowercased before it is stored and checked. Unique within the project; `go`, `embed`, `portal`, `bot`, `direct`, `new` and `edit` are reserved. Such as `youtube`.",
                        "pattern": "^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$",
                        "minLength": 2,
                        "maxLength": 32
                    },
                    "destination": {
                        "description": "`portal` (the portal home), `plan` (the checkout of one plan, which needs `plan_id`) or `bot` (the project's bot; the portal home when no bot is connected).",
                        "$ref": "#/components/schemas/SmartLinkDestination"
                    },
                    "plan_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The plan a `plan` destination opens; one of this project's plans. Refused as meaningless on the other destinations."
                    },
                    "expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the link stops counting and crediting, ISO 8601, in the future. Omit for never; the address keeps landing on the portal home after it."
                    }
                },
                "required": [
                    "name",
                    "slug",
                    "destination"
                ],
                "title": "StoreSmartLinkRequest"
            },
            "StoreSupportCannedReplyRequest": {
                "type": "object",
                "description": "A new saved reply: the words, the label the picker shows and, optionally, the shortcut and position.",
                "properties": {
                    "title": {
                        "type": "string",
                        "description": "The label shown in the picker, 2 to 80 characters; never sent to the member.",
                        "minLength": 2,
                        "maxLength": 80
                    },
                    "body": {
                        "type": "string",
                        "description": "The text sent to the member, 2 to 4,000 characters, the message ceiling the reply has to fit once it is sent.",
                        "minLength": 2,
                        "maxLength": 4000
                    },
                    "shortcut": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Up to 30 letters, numbers, dashes and underscores, unique within the project (two projects may both have `hours`). Omit it, or send null or an empty string, for none. The character set means a shortcut can never be confused with a bot command or need escaping when echoed back.",
                        "pattern": "^[A-Za-z0-9_-]+$",
                        "maxLength": 30
                    },
                    "sort_order": {
                        "type": "integer",
                        "description": "The position in the picker, 0 to 999. Defaults to 0.",
                        "minimum": 0,
                        "maximum": 999
                    }
                },
                "required": [
                    "title",
                    "body"
                ],
                "title": "StoreSupportCannedReplyRequest"
            },
            "StoreTeamRequest": {
                "type": "object",
                "description": "A team's name: required on create, optional on update. Ownership does not transfer through this body, and membership moves through its own routes.",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "The team's name, up to 255 characters; the only mutable field.",
                        "maxLength": 255
                    }
                },
                "required": [
                    "name"
                ],
                "title": "StoreTeamRequest"
            },
            "StoreTokenRequest": {
                "type": "object",
                "description": "A token to mint: its label, the abilities it holds and the team it is minted for. The abilities must be a subset of the calling token's, and `token:create` is never granted this way.",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "A label for the token, up to 255 characters, shown on Settings → API Tokens.",
                        "maxLength": 255
                    },
                    "abilities": {
                        "type": "array",
                        "description": "The abilities the token holds, at least one. Each must be one the calling token holds itself (attenuation), and `token:create` is withheld unconditionally.",
                        "items": {
                            "type": "string",
                            "description": "An ability string from the catalog. A retired ability cannot be granted to a new token; the refusal names its replacements."
                        },
                        "minItems": 1
                    },
                    "team_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The team the token is minted **for**; it receives `scope:team:<team_id>` automatically and cannot be widened later. Must be a team the caller owns or belongs to. Required here, unlike everywhere else in v1 where the team comes from the calling token's scope."
                    }
                },
                "required": [
                    "name",
                    "abilities",
                    "team_id"
                ],
                "title": "StoreTokenRequest"
            },
            "StoreWebhookEndpointRequest": {
                "type": "object",
                "description": "A webhook endpoint to register: where to post, which events, and how to confine it. The signing secret is minted by Subscriby and returned once beside the endpoint.",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "A label for the endpoint, 3 to 100 characters.",
                        "minLength": 3,
                        "maxLength": 100
                    },
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "description": "The target, `https://` only, up to 2,048 characters, pointing at a public host: loopback, private, link-local and reserved addresses are refused, as is a public hostname that resolves to one.",
                        "maxLength": 2048
                    },
                    "project_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uuid",
                        "description": "Confine the endpoint to one project's events; omit it for a team-wide subscription."
                    },
                    "events": {
                        "type": "array",
                        "description": "The events to subscribe to, at least one.",
                        "items": {
                            "type": "string",
                            "description": "An event name from the webhook event catalog, such as `subscription.created`; an unknown name is refused.",
                            "enum": [
                                "project.created",
                                "project.updated",
                                "project.archived",
                                "project.restored",
                                "project.deleted",
                                "project.design_published",
                                "project.resource.created",
                                "project.resource.linked",
                                "project.resource.unlinked",
                                "project.resource.deleted",
                                "project.resource.updated",
                                "project.resource.status_changed",
                                "project.payment_method.updated",
                                "project.payment_method.deleted",
                                "plan.created",
                                "plan.updated",
                                "plan.activated",
                                "plan.deactivated",
                                "plan.sold_out",
                                "plan.order_changed",
                                "plan.deleted",
                                "plan.sync_completed",
                                "pass.window_scheduled",
                                "pass.window_opened",
                                "pass.window_closed",
                                "pass.window_cancelled",
                                "pass.holder_queued",
                                "pass.holder_moved",
                                "pass.holder_missed",
                                "pass.holder_stranded",
                                "pass_series.purchased",
                                "pass_series.leg_added",
                                "pass_series.leg_completed",
                                "pass_series.leg_substituted",
                                "pass_series.leg_dropped",
                                "pass_series.seats_exhausted",
                                "pass_series.completed",
                                "pass_series.presale_opened",
                                "coupon.created",
                                "coupon.updated",
                                "coupon.activated",
                                "coupon.deactivated",
                                "coupon.deleted",
                                "coupon.redeemed",
                                "coupon.exhausted",
                                "referral.program_updated",
                                "referral.affiliate_joined",
                                "referral.affiliate_approved",
                                "referral.affiliate_suspended",
                                "referral.captured",
                                "referral.converted",
                                "referral.reward_earned",
                                "referral.reward_approved",
                                "referral.reward_reversed",
                                "referral.payout_recorded",
                                "partner.referral_signed_up",
                                "partner.referral_converted",
                                "partner.reward_earned",
                                "partner.reward_approved",
                                "partner.reward_credited",
                                "partner.reward_reversed",
                                "partner.payout_recorded",
                                "partner.application_approved",
                                "partner.application_rejected",
                                "partner.rate_changed",
                                "copilot_credit.purchased",
                                "copilot_credit.granted",
                                "copilot_credit.low",
                                "copilot_credit.refunded",
                                "knowledge.created",
                                "knowledge.updated",
                                "knowledge.deleted",
                                "link.created",
                                "link.updated",
                                "link.archived",
                                "subscription.created",
                                "subscription.activated",
                                "subscription.trial_started",
                                "subscription.trial_converting",
                                "subscription.trial_expired",
                                "subscription.renewed",
                                "subscription.reactivated",
                                "subscription.paused",
                                "subscription.unpaused",
                                "subscription.past_due",
                                "subscription.unpaid",
                                "subscription.cancelled",
                                "subscription.expired",
                                "subscription.refunded",
                                "subscription.upgraded",
                                "subscription.downgraded",
                                "subscription.payment_recovered",
                                "subscription.access_suspended",
                                "subscription.access_restored",
                                "subscription.cancellation_feedback",
                                "subscription.offer_taken",
                                "sequence.created",
                                "sequence.updated",
                                "sequence.deleted",
                                "sequence.enrolled",
                                "sequence.step_sent",
                                "sequence.converted",
                                "sequence.exited",
                                "payment.succeeded",
                                "payment.failed",
                                "payment.pending",
                                "payment.refunded",
                                "checkout.stalled",
                                "checkout.recovered",
                                "member.lead_created",
                                "member.joined",
                                "member.trial_joined",
                                "member.converted",
                                "member.churned",
                                "member.removed",
                                "member.banned",
                                "member.unbanned",
                                "member.kicked",
                                "member.resource_added",
                                "member.resource_pending",
                                "member.resource_reissued",
                                "member.access_extended",
                                "member.resource_removed",
                                "member.identity_linked",
                                "member.identity_unlinked",
                                "creator_task.opened",
                                "creator_task.completed",
                                "connector.installed",
                                "connector.connected",
                                "connector.disconnected",
                                "connector.status_changed",
                                "connector.settings_updated",
                                "connector.uninstalled",
                                "connector.doctor_completed",
                                "connector.outage_opened",
                                "connector.outage_closed",
                                "connector.outage_compensated",
                                "recovery.incident_opened",
                                "recovery.incident_resolved",
                                "recovery.operation_started",
                                "recovery.operation_completed",
                                "recovery.operation_failed",
                                "recovery.operation_reverted",
                                "recovery.standby_registered",
                                "recovery.standby_removed",
                                "recovery.installation_failed_over",
                                "recovery.resource_failed_over",
                                "recovery.resource_replaced",
                                "recovery.identity_relinked",
                                "recovery.readiness_changed",
                                "broadcast.queued",
                                "broadcast.completed",
                                "access_code.generated",
                                "access_code.redeemed",
                                "access_code.expired",
                                "support.conversation.opened",
                                "support.conversation.assigned",
                                "support.conversation.resolved",
                                "support.conversation.reopened",
                                "support.conversation.blocked",
                                "support.conversation.unblocked",
                                "support.message.received",
                                "support.message.sent",
                                "support.canned_reply.created",
                                "support.canned_reply.updated",
                                "support.canned_reply.deleted",
                                "support.settings.updated",
                                "team.created",
                                "team.updated",
                                "team.deleted",
                                "team.member.invited",
                                "team.member.joined",
                                "team.member.removed",
                                "team.member.role_changed",
                                "role.created",
                                "role.updated",
                                "role.deleted",
                                "group.created",
                                "group.updated",
                                "group.members_synced",
                                "group.deleted",
                                "billing.invoice_created",
                                "billing.invoice_paid",
                                "billing.invoice_overdue",
                                "billing.payment_failed",
                                "billing.trial_ending",
                                "billing.grace_period_warning",
                                "billing.account_locked",
                                "billing.tier_upgraded",
                                "billing.tier_downgraded",
                                "billing.tier_cancelled"
                            ]
                        },
                        "minItems": 1
                    },
                    "allowed_ips": {
                        "type": [
                            "array",
                            "null"
                        ],
                        "description": "IPv4/IPv6 addresses or CIDR ranges the target must resolve to. Enforced on every delivery: when the endpoint's host resolves to an address outside the list, the delivery is dead-lettered without being posted.",
                        "items": {
                            "type": "string",
                            "description": "An address or CIDR range, such as `198.51.100.7` or `2001:db8::/32`."
                        }
                    },
                    "is_active": {
                        "type": "boolean",
                        "description": "Whether deliveries flow from the start. Defaults to true."
                    }
                },
                "required": [
                    "name",
                    "url",
                    "events"
                ],
                "title": "StoreWebhookEndpointRequest"
            },
            "StorefrontArrangement": {
                "type": "string",
                "description": "How a project's storefront orders the plans it offers. `Manual` is the order the creator pinned by drag and drop, with the built-in order (passes, then seasons, then subscriptions, cheapest first) behind it. `Live` re-arranges the offered plans at read time by what the clock says: a pass or season whose access is on now comes first, the one ending soonest at the top, then the ones opening soonest, then everything else in the manual order. It exists because a creator selling dated passes cannot keep dragging the current one to the top, and it is gated on the owner's time-limited passes capability, since only a project with passes has anything to arrange by.\n",
                "enum": [
                    "manual",
                    "live"
                ],
                "title": "StorefrontArrangement"
            },
            "SubscriptionBillingCycle": {
                "type": "string",
                "description": "The unit a creator's own subscription plan renews in. Not the platform cycle: this is what a creator sells to their members, and it pairs with a count (`billing_cycle_count`) so \"3 months\" and \"2 weeks\" are both expressible. `Lifetime` is a one-time purchase that never renews.\n",
                "enum": [
                    "day",
                    "week",
                    "month",
                    "year",
                    "lifetime"
                ],
                "examples": [
                    "month"
                ],
                "title": "SubscriptionBillingCycle"
            },
            "SubscriptionResource": {
                "type": "object",
                "description": "A subscription: one member's purchase of a plan, held or still an unredeemed access code, with its payment state and, on the detail read, its access grants.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The subscription's id.",
                        "examples": [
                            "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                        ]
                    },
                    "plan_id": {
                        "type": "string",
                        "description": "The plan that was bought.",
                        "examples": [
                            "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b"
                        ]
                    },
                    "subscriber_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The member who holds it.",
                        "examples": [
                            "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                        ]
                    },
                    "method_id": {
                        "type": "string",
                        "description": "The payment method it was bought through; null for an access code.",
                        "examples": [
                            "8b0c4a15-e792-4360-95d8-1f47c0b3e926"
                        ]
                    },
                    "payment_status": {
                        "description": "Where the purchase stands: `trialing`, `active`, `incomplete`, `expired`, `past_due`, `canceled`, `unpaid`, `paused`, `processing`, `succeeded`, `capturable` or `failed`.",
                        "anyOf": [
                            {
                                "$ref": "#/components/schemas/SubscriptionStatus"
                            },
                            {
                                "type": "string",
                                "enum": [
                                    "trialing",
                                    "active",
                                    "incomplete",
                                    "expired",
                                    "past_due",
                                    "canceled",
                                    "unpaid",
                                    "paused",
                                    "processing",
                                    "succeeded",
                                    "capturable",
                                    "failed",
                                    "pending"
                                ],
                                "examples": [
                                    "active"
                                ]
                            }
                        ]
                    },
                    "payment_price": {
                        "type": "string",
                        "description": "What the member pays per period, as a decimal string in the plan's currency.",
                        "examples": [
                            "29.00"
                        ]
                    },
                    "currency_id": {
                        "type": "string",
                        "description": "The currency the price is in.",
                        "examples": [
                            "8f27a0d4-63be-4915-8c07-1a5d9e34b628"
                        ]
                    },
                    "trial_ends_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the trial ends, ISO 8601; null without a trial.",
                        "examples": [
                            null
                        ]
                    },
                    "ends_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the current access ends, ISO 8601, `compensation_seconds` already included: a one-time purchase simply ends later, while a recurring plan's `ends_at` runs that many seconds past the period the member last paid for. Null while open-ended.",
                        "examples": [
                            "2026-06-18T10:05:00Z"
                        ]
                    },
                    "canceled": {
                        "type": "boolean",
                        "description": "Whether a cancellation is scheduled or done; the access runs to `ends_at`.",
                        "examples": [
                            false
                        ]
                    },
                    "compensation_seconds": {
                        "type": "integer",
                        "description": "The outage time Outage Compensation has banked on the purchase, 0 for almost every subscription; the renewal the gateway bills is `ends_at` minus this.",
                        "examples": [
                            0
                        ]
                    },
                    "redeemed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When an access code was redeemed, ISO 8601; null for a paid purchase or an unredeemed code.",
                        "examples": [
                            null
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the purchase was made, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the row last changed, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    },
                    "source": {
                        "type": [
                            "array",
                            "null"
                        ],
                        "description": "Where the subscriber came from: the Smart Link credited with them, the door and the campaign tags, read from the member. Null for a member who arrived with no link and no tags; present on a single read and on a list.",
                        "items": {}
                    },
                    "grants": {
                        "type": "array",
                        "description": "The access ledger rows, one per resource and dated window; embedded on the detail read only, never on the list.",
                        "items": {
                            "$ref": "#/components/schemas/AccessGrantResource"
                        }
                    }
                },
                "required": [
                    "id",
                    "plan_id",
                    "subscriber_id",
                    "method_id",
                    "payment_status",
                    "payment_price",
                    "currency_id",
                    "trial_ends_at",
                    "ends_at",
                    "canceled",
                    "compensation_seconds",
                    "redeemed_at",
                    "created_at",
                    "updated_at"
                ],
                "title": "SubscriptionResource"
            },
            "SubscriptionStatus": {
                "type": "string",
                "enum": [
                    "trialing",
                    "active",
                    "incomplete",
                    "expired",
                    "past_due",
                    "canceled",
                    "unpaid",
                    "paused",
                    "processing",
                    "succeeded",
                    "capturable",
                    "failed",
                    "pending"
                ],
                "examples": [
                    "active"
                ],
                "title": "SubscriptionStatus"
            },
            "SupportCannedReplyResource": {
                "type": "object",
                "description": "A saved reply: a reusable snippet the support inbox composer expands from a shortcut or picks from a list.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The snippet's id.",
                        "examples": [
                            "1f7c9a3e-52d8-4b16-a0e4-8c3b7d29f615"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the snippet belongs to.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "title": {
                        "type": "string",
                        "description": "The label shown in the picker, 2 to 80 characters; never sent to the member.",
                        "examples": [
                            "Opening hours"
                        ]
                    },
                    "body": {
                        "type": "string",
                        "description": "The text sent to the member when the snippet is used, 2 to 4,000 characters.",
                        "examples": [
                            "We answer between 9 and 5, Monday to Friday. Anything sent outside that is picked up the next working morning."
                        ]
                    },
                    "shortcut": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the creator types in the composer to pull the snippet in, up to 30 letters, numbers, dashes and underscores, unique within the project; null when the snippet is picked from the list instead.",
                        "examples": [
                            "hours"
                        ]
                    },
                    "sort_order": {
                        "type": "integer",
                        "description": "The snippet's position in the picker, 0 to 999.",
                        "examples": [
                            0
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the snippet was created, ISO 8601.",
                        "examples": [
                            "2026-09-06T10:05:00+00:00"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the snippet last changed, ISO 8601.",
                        "examples": [
                            "2026-09-06T10:05:00+00:00"
                        ]
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "title",
                    "body",
                    "shortcut",
                    "sort_order",
                    "created_at",
                    "updated_at"
                ],
                "title": "SupportCannedReplyResource"
            },
            "SupportConversationResource": {
                "type": "object",
                "description": "A support conversation: the one durable thread between a project and a member on one connector.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The conversation's id.",
                        "examples": [
                            "9e042b6f-5d81-4c37-a920-7b3e18cf6d45"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project whose bot the member wrote to.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "subscriber_id": {
                        "type": "string",
                        "description": "The member behind the thread; may be a `lead` who never paid, since anyone who can reach the bot can open a conversation.",
                        "examples": [
                            "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                        ]
                    },
                    "member_name": {
                        "type": "string",
                        "description": "The member's display name, or \"Unknown member\" when they have not shared one, so a picker has something human to show.",
                        "examples": [
                            "Jane Doe"
                        ]
                    },
                    "channel": {
                        "type": "string",
                        "description": "The key of the connector the member wrote through. A member who writes through two connectors has two conversations, and each reply goes back on the connector its conversation came in on.",
                        "examples": [
                            "telegram"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "`open`, `pending`, `snoozed` or `resolved`.",
                        "enum": [
                            "open",
                            "pending",
                            "snoozed",
                            "resolved"
                        ],
                        "examples": [
                            "open"
                        ]
                    },
                    "assigned_to_user_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The team member the thread is assigned to; null when unassigned.",
                        "examples": [
                            null
                        ]
                    },
                    "subject": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A subject line, when the inbox set one; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "unread_count": {
                        "type": "integer",
                        "description": "How many inbound messages the team has not read.",
                        "examples": [
                            2
                        ]
                    },
                    "blocked": {
                        "type": "boolean",
                        "description": "True when inbound messages from the member are being dropped: the thread is history only and cannot reopen on inbound.",
                        "examples": [
                            false
                        ]
                    },
                    "last_message_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the newest message, either way, arrived, ISO 8601.",
                        "examples": [
                            "2026-08-20T10:05:00Z"
                        ]
                    },
                    "last_inbound_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the member last wrote, ISO 8601; null if never.",
                        "examples": [
                            "2026-08-20T10:05:00Z"
                        ]
                    },
                    "last_outbound_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the team last replied, ISO 8601; null if never.",
                        "examples": [
                            null
                        ]
                    },
                    "first_response_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Stamped **once**, on the first human reply ever in the thread: an SLA measure of how long the member waited for a person, not of the most recent reply. A reopen does not reset it.",
                        "examples": [
                            null
                        ]
                    },
                    "resolved_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the thread was last resolved, ISO 8601; null while open.",
                        "examples": [
                            null
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the thread opened, ISO 8601.",
                        "examples": [
                            "2026-08-20T10:05:00Z"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the thread last changed, ISO 8601.",
                        "examples": [
                            "2026-08-20T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "project_id",
                    "subscriber_id",
                    "member_name",
                    "channel",
                    "status",
                    "assigned_to_user_id",
                    "subject",
                    "unread_count",
                    "blocked",
                    "last_message_at",
                    "last_inbound_at",
                    "last_outbound_at",
                    "first_response_at",
                    "resolved_at",
                    "created_at",
                    "updated_at"
                ],
                "title": "SupportConversationResource"
            },
            "SupportMessageResource": {
                "type": "object",
                "description": "One message in a support thread: who wrote it, through which surface, whether it reached the member, and its attachments without the connector's file ids.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The message's id, the value `reply_to_message_id` quotes.",
                        "examples": [
                            "6c18f7a3-2e95-4d60-b47a-c093e5182b7f"
                        ]
                    },
                    "conversation_id": {
                        "type": "string",
                        "description": "The thread the message belongs to.",
                        "examples": [
                            "9e042b6f-5d81-4c37-a920-7b3e18cf6d45"
                        ]
                    },
                    "project_id": {
                        "type": "string",
                        "description": "The project the thread belongs to.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "direction": {
                        "type": "string",
                        "description": "`inbound` (from the member) or `outbound` (from the team).",
                        "enum": [
                            "inbound",
                            "outbound"
                        ],
                        "examples": [
                            "inbound"
                        ]
                    },
                    "author_kind": {
                        "type": "string",
                        "description": "`contact` (the member), `creator` (a team member) or `system`.",
                        "enum": [
                            "contact",
                            "creator",
                            "system",
                            "assistant"
                        ],
                        "examples": [
                            "contact"
                        ]
                    },
                    "author_user_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The team member who wrote an outbound reply; null for inbound and system messages.",
                        "examples": [
                            null
                        ]
                    },
                    "type": {
                        "type": "string",
                        "description": "What the message carries: `text`, `photo`, `video`, `audio`, `voice`, `document`, `sticker`, `animation`, `location` or `contact`.",
                        "enum": [
                            "text",
                            "photo",
                            "video",
                            "audio",
                            "voice",
                            "document",
                            "sticker",
                            "animation",
                            "location",
                            "contact",
                            "note",
                            "system"
                        ],
                        "examples": [
                            "text"
                        ]
                    },
                    "source": {
                        "type": "string",
                        "description": "The surface the message came through: `connector_chat` for a member writing to the connector's installation, `dashboard`, `api` or `mcp` for a reply from the team, `connector_relay_dm` or `connector_relay_group` for a reply the team typed on the platform itself, `ai_assistant` for a drafted reply. Messages recorded before the connector SDK carry the same meanings under the first connector's older words, its key followed by `_bot`, `_relay_dm` and `_relay_group`.",
                        "enum": [
                            "connector_chat",
                            "connector_relay_dm",
                            "connector_relay_group",
                            "dashboard",
                            "api",
                            "mcp",
                            "ai_assistant"
                        ],
                        "examples": [
                            "connector_chat"
                        ]
                    },
                    "delivery_status": {
                        "type": "string",
                        "description": "On an outbound message, `pending` then `sent`, or `failed` / `unreachable`. **`unreachable` means the member has blocked the bot**: the reply is stored but will never arrive, and retrying will not help.",
                        "enum": [
                            "pending",
                            "sent",
                            "failed",
                            "unreachable",
                            "draft",
                            "suppressed"
                        ],
                        "examples": [
                            "sent"
                        ]
                    },
                    "body": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The text, or the caption of a media message; null for media sent without a caption.",
                        "examples": [
                            "My invite link expired before I could join"
                        ]
                    },
                    "internal": {
                        "type": "boolean",
                        "description": "True for a private note the team wrote for itself, never delivered to the member. Withheld from tokens that cannot update the conversation.",
                        "examples": [
                            false
                        ]
                    },
                    "reply_to_message_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The earlier message this one quotes; null when it quotes none.",
                        "examples": [
                            null
                        ]
                    },
                    "attachments": {
                        "type": "array",
                        "description": "The files on the message, described without the connector's file ids, which are credentials.",
                        "items": {
                            "type": "object",
                            "description": "One attachment.",
                            "properties": {
                                "kind": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "What the file is: `photo`, `video`, `audio`, `voice`, `document`, `sticker` or `animation`.",
                                    "examples": [
                                        "photo"
                                    ]
                                },
                                "mime": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The MIME type, when the platform gave one.",
                                    "examples": [
                                        "image/jpeg"
                                    ]
                                },
                                "file_name": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The original file name, when the platform gave one.",
                                    "examples": [
                                        null
                                    ]
                                },
                                "size": {
                                    "type": [
                                        "integer",
                                        "null"
                                    ],
                                    "description": "The size in bytes, when known.",
                                    "examples": [
                                        84213
                                    ]
                                },
                                "width": {
                                    "type": [
                                        "integer",
                                        "null"
                                    ],
                                    "description": "The width in pixels for an image or video; null otherwise.",
                                    "examples": [
                                        1280
                                    ]
                                },
                                "height": {
                                    "type": [
                                        "integer",
                                        "null"
                                    ],
                                    "description": "The height in pixels for an image or video; null otherwise.",
                                    "examples": [
                                        720
                                    ]
                                },
                                "duration": {
                                    "type": [
                                        "integer",
                                        "null"
                                    ],
                                    "description": "The length in seconds for audio and video; null otherwise.",
                                    "examples": [
                                        null
                                    ]
                                },
                                "url": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The stored copy's URL, populated only after the file has been fetched at least once; null until then.",
                                    "examples": [
                                        "https://static.subscriby.net/support/6c18f7a3.jpg"
                                    ]
                                }
                            },
                            "required": [
                                "kind",
                                "mime",
                                "file_name",
                                "size",
                                "width",
                                "height",
                                "duration",
                                "url"
                            ]
                        }
                    },
                    "failure_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why an outbound message `failed` or is `unreachable`; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "edited_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the member edited the message, ISO 8601; the stored message is updated in place and no event fires. Null when never edited.",
                        "examples": [
                            null
                        ]
                    },
                    "read_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the team read an inbound message, ISO 8601; null while unread.",
                        "examples": [
                            null
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the message was recorded, ISO 8601.",
                        "examples": [
                            "2026-08-20T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "conversation_id",
                    "project_id",
                    "direction",
                    "author_kind",
                    "author_user_id",
                    "type",
                    "source",
                    "delivery_status",
                    "body",
                    "internal",
                    "reply_to_message_id",
                    "attachments",
                    "failure_reason",
                    "edited_at",
                    "read_at",
                    "created_at"
                ],
                "title": "SupportMessageResource"
            },
            "SupportSettingsResource": {
                "type": "object",
                "description": "A project's support inbox settings: whether members can open a conversation, how the creator is relayed, the agent name, the auto-reply and email notifications.",
                "properties": {
                    "project_id": {
                        "type": "string",
                        "description": "The project the settings belong to.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "enabled": {
                        "type": "boolean",
                        "description": "Whether a member's unrecognised message to the bot opens a conversation. Off stops **new** threads reaching the inbox; existing ones are kept.",
                        "examples": [
                            true
                        ]
                    },
                    "relay_mode": {
                        "type": "string",
                        "description": "`owner_dm` (the platform bot messages the project owner with an inline Reply button), `forum_group` (each conversation mirrored into its own topic of a group the bot administers) or `none` (the dashboard inbox is the only surface).",
                        "enum": [
                            "none",
                            "owner_dm",
                            "forum_group"
                        ],
                        "examples": [
                            "owner_dm"
                        ]
                    },
                    "agent_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The name outbound replies are prefixed with so they read as coming from a person; null falls back to the project's default.",
                        "examples": [
                            "Team Subscriby"
                        ]
                    },
                    "auto_reply": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Sent to a member on their first message in a thread; null sends nothing.",
                        "examples": [
                            "Thanks, a person will reply within a day."
                        ]
                    },
                    "notify_email": {
                        "type": "boolean",
                        "description": "Whether the creator is emailed about new support activity.",
                        "examples": [
                            false
                        ]
                    },
                    "copilot_answers": {
                        "type": "boolean",
                        "description": "Whether Subscriby Copilot answers members' own-subscription questions and what the project's Knowledge covers in the inbox and the project bot, marked as automated.",
                        "examples": [
                            false
                        ]
                    },
                    "copilot_portal": {
                        "type": "boolean",
                        "description": "Whether a signed-in member finds the Copilot in a chat on the portal page.",
                        "examples": [
                            false
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the project last changed, ISO 8601.",
                        "examples": [
                            "2026-09-06T10:05:00+00:00"
                        ]
                    }
                },
                "required": [
                    "project_id",
                    "enabled",
                    "relay_mode",
                    "agent_name",
                    "auto_reply",
                    "notify_email",
                    "copilot_answers",
                    "copilot_portal",
                    "updated_at"
                ],
                "title": "SupportSettingsResource"
            },
            "SyncGroupMembersRequest": {
                "type": "object",
                "description": "The group's complete membership after the call. A sync, not an add: anyone omitted is removed, and `[]` empties the group.",
                "properties": {
                    "user_ids": {
                        "type": "array",
                        "description": "Every user the group should have afterwards. Must be present; `[]` empties the group. Each id must already belong to the group's team, or the whole call is refused naming the outsiders.",
                        "items": {
                            "type": "string",
                            "format": "uuid",
                            "description": "A user id of a member of the group's team."
                        }
                    }
                },
                "required": [
                    "user_ids"
                ],
                "title": "SyncGroupMembersRequest"
            },
            "TeamMemberResource": {
                "type": "object",
                "description": "One person's place on a team: their profile plus their role on the queried team. The owner's pseudo-row carries `is_owner: true` and a null role.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The collaborator's user id, the value the member routes take.",
                        "examples": [
                            "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                        ]
                    },
                    "team_id": {
                        "type": "string",
                        "description": "The team the membership is on.",
                        "examples": [
                            "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86"
                        ]
                    },
                    "name": {
                        "type": "string",
                        "description": "The collaborator's name.",
                        "examples": [
                            "Priya Patel"
                        ]
                    },
                    "email": {
                        "type": "string",
                        "description": "The collaborator's email address. Present only for a token holding `team-member:view`; a roster-only token gets no `email` key at all, not null. The show route requires that ability, so it always includes it.",
                        "examples": [
                            "priya@example.com"
                        ]
                    },
                    "role_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The role the collaborator holds on this team, or null for the owner pseudo-row.",
                        "examples": [
                            "d05e1a83-7c46-4f29-b613-8ae407c9d251"
                        ]
                    },
                    "is_owner": {
                        "type": "boolean",
                        "description": "True only for the single team creator, who is returned alongside the members but bypasses the membership table entirely.",
                        "examples": [
                            false
                        ]
                    },
                    "joined_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the collaborator joined, ISO 8601; the team's creation for the owner.",
                        "examples": [
                            "2026-04-02T14:15:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "team_id",
                    "name",
                    "role_id",
                    "is_owner",
                    "joined_at"
                ],
                "title": "TeamMemberResource"
            },
            "TeamResource": {
                "type": "object",
                "description": "A team: the tenant every project, role and group hangs off. Every creator owns a personal team; further teams are a Growth capability.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The team's id, the value a token's team scope names.",
                        "examples": [
                            "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86"
                        ]
                    },
                    "name": {
                        "type": "string",
                        "description": "The team's name.",
                        "examples": [
                            "Research Collective"
                        ]
                    },
                    "owner_user_id": {
                        "type": "string",
                        "description": "The user who owns the team; deleting it is theirs alone.",
                        "examples": [
                            "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80"
                        ]
                    },
                    "personal": {
                        "type": "boolean",
                        "description": "Whether this is the creator's personal team, the one created with the account, which cannot be deleted.",
                        "examples": [
                            false
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the team was created, ISO 8601.",
                        "examples": [
                            "2026-01-12T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "name",
                    "owner_user_id",
                    "personal",
                    "created_at"
                ],
                "title": "TeamResource"
            },
            "TokenResource": {
                "type": "object",
                "description": "One of the caller's personal access tokens, without its value. The plaintext exists exactly once, in the response that minted it.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The token's id: an **integer** serialised as a string, the one identifier in the platform that is not a UUID.",
                        "examples": [
                            "1284"
                        ]
                    },
                    "name": {
                        "type": "string",
                        "description": "The label the token was minted with.",
                        "examples": [
                            "Zapier production"
                        ]
                    },
                    "abilities": {
                        "type": "array",
                        "description": "The gate abilities only; the scope tuples are split out into `scopes`.",
                        "items": {
                            "description": "An ability string, as the ability catalog lists them.",
                            "examples": [
                                "project:view-any"
                            ]
                        }
                    },
                    "scopes": {
                        "type": "object",
                        "description": "The token's confinement, read out of its `scope:team:` and `scope:project:` abilities as structure rather than opaque strings.",
                        "properties": {
                            "team_id": {
                                "type": "string",
                                "description": "The team the token is scoped to; null for a token minted without a team scope.",
                                "examples": [
                                    "a83f0d51-4c92-4b7e-8615-2fd9e70a3c86"
                                ]
                            },
                            "project_ids": {
                                "type": "array",
                                "description": "The projects the token is confined to; empty when it reaches every project of the team.",
                                "items": {
                                    "type": "string",
                                    "description": "A project id.",
                                    "examples": [
                                        "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                                    ]
                                }
                            }
                        },
                        "required": [
                            "team_id",
                            "project_ids"
                        ]
                    },
                    "abilities_count": {
                        "type": "integer",
                        "description": "How many gate abilities the token holds, bookkeeping excluded.",
                        "examples": [
                            2
                        ]
                    },
                    "last_used_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the token last authenticated a request, ISO 8601; null until it has.",
                        "examples": [
                            "2026-05-18T09:15:00Z"
                        ]
                    },
                    "expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the token stops working, ISO 8601; null for a token that does not expire.",
                        "examples": [
                            null
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the token was minted, ISO 8601.",
                        "examples": [
                            "2026-05-01T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "name",
                    "abilities",
                    "scopes",
                    "abilities_count",
                    "last_used_at",
                    "expires_at",
                    "created_at"
                ],
                "title": "TokenResource"
            },
            "TransactionFeeInvoiceResource": {
                "type": "object",
                "description": "One Subscriby invoice that billed metered lines of the month: its Stripe id, what those lines add up to, the meter units behind them, how many lines it billed and when it was paid.",
                "properties": {
                    "invoice_id": {
                        "type": "string",
                        "description": "The Stripe invoice id, the one on your receipt.",
                        "examples": [
                            "in_1QExampleInvoice00"
                        ]
                    },
                    "fee": {
                        "type": "string",
                        "description": "What the lines it billed add up to, as a decimal string with four places.",
                        "examples": [
                            "12.4800"
                        ]
                    },
                    "units": {
                        "type": "integer",
                        "description": "The cents the meter counted on those lines.",
                        "examples": [
                            1248
                        ]
                    },
                    "rows": {
                        "type": "integer",
                        "description": "How many lines it billed.",
                        "examples": [
                            27
                        ]
                    },
                    "invoiced_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the invoice was paid, ISO 8601.",
                        "examples": [
                            "2026-11-01T06:30:12+00:00"
                        ]
                    }
                },
                "required": [
                    "invoice_id",
                    "fee",
                    "units",
                    "rows",
                    "invoiced_at"
                ],
                "title": "TransactionFeeInvoiceResource"
            },
            "TransactionFeeKindShareResource": {
                "type": "object",
                "description": "One kind of fee inside the month: its value, its label in the creator's language, what its lines add up to, the meter units behind them and how many lines there are.",
                "properties": {
                    "kind": {
                        "type": "string",
                        "description": "The kind's value, such as `payment_fee`.",
                        "enum": [
                            "payment_fee",
                            "access_code_fee",
                            "trial_usage",
                            "outage_emails",
                            "processing_recovery"
                        ],
                        "examples": [
                            "payment_fee"
                        ]
                    },
                    "label": {
                        "type": "string",
                        "description": "The kind in the creator's language.",
                        "examples": [
                            "Payment Fee"
                        ]
                    },
                    "fee": {
                        "type": "string",
                        "description": "What the lines of that kind add up to, as a decimal string with four places.",
                        "examples": [
                            "46.1100"
                        ]
                    },
                    "units": {
                        "type": "integer",
                        "description": "The cents the meter counted for them; zero when every line was taken at source.",
                        "examples": [
                            1491
                        ]
                    },
                    "rows": {
                        "type": "integer",
                        "description": "How many lines of that kind the month holds.",
                        "examples": [
                            38
                        ]
                    }
                },
                "required": [
                    "kind",
                    "label",
                    "fee",
                    "units",
                    "rows"
                ],
                "title": "TransactionFeeKindShareResource"
            },
            "TransactionFeeProjectShareResource": {
                "type": "object",
                "description": "One project inside the month: its id and name, what its lines add up to and how many there are; the fees no project carries pool under a null id.",
                "properties": {
                    "project_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The project, or null for the fees no project carries (a trial's waived fees, an invoice's processing recovery).",
                        "examples": [
                            "0f1e2d3c-4b5a-4968-8776-655443322110"
                        ]
                    },
                    "name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The project's name; null for the pooled share and for a project since deleted.",
                        "examples": [
                            "Acme Club"
                        ]
                    },
                    "fee": {
                        "type": "string",
                        "description": "What the project's lines add up to, as a decimal string with four places.",
                        "examples": [
                            "47.2800"
                        ]
                    },
                    "rows": {
                        "type": "integer",
                        "description": "How many lines the project holds in the month.",
                        "examples": [
                            39
                        ]
                    }
                },
                "required": [
                    "project_id",
                    "name",
                    "fee",
                    "rows"
                ],
                "title": "TransactionFeeProjectShareResource"
            },
            "TransactionFeeResource": {
                "type": "object",
                "description": "A transaction fee Subscriby charged the caller: what it was for, the payment it was priced from where there was one, the rate and the amount as decimal strings, how it was collected, and the Subscriby invoice that billed it once one has.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The line's id.",
                        "examples": [
                            "7d2f9b4e-3c1a-4e5b-9f6d-2a8b7c6d5e4f"
                        ]
                    },
                    "kind": {
                        "type": "string",
                        "description": "What the fee was for: `payment_fee` (the commission on a member's payment), `access_code_fee` (a code redeemed past the plan's free allotment), `trial_usage` (the metered fees a platform trial waived, collected once the trial ended), `outage_emails` (emails sent to members on your behalf during a recovery) or `processing_recovery` (the cost of collecting an invoice's fee lines, metered for the next cycle).",
                        "enum": [
                            "payment_fee",
                            "access_code_fee",
                            "trial_usage",
                            "outage_emails",
                            "processing_recovery"
                        ],
                        "examples": [
                            "payment_fee"
                        ]
                    },
                    "kind_label": {
                        "type": "string",
                        "description": "The kind in the creator's language.",
                        "enum": [
                            "Payment Fee",
                            "Access Code Fee",
                            "Trial Usage",
                            "Recovery Emails",
                            "Processing Recovery"
                        ],
                        "examples": [
                            "Payment Fee"
                        ]
                    },
                    "channel": {
                        "type": "string",
                        "description": "How it was collected: `connect_at_source` (deducted from the member's payment by Stripe Connect, never invoiced) or `metered` (reported to the usage meter and billed on your own Subscriby invoice).",
                        "enum": [
                            "connect_at_source",
                            "metered"
                        ],
                        "examples": [
                            "metered"
                        ]
                    },
                    "channel_label": {
                        "type": "string",
                        "description": "The channel in the creator's language.",
                        "enum": [
                            "Taken at Source",
                            "Billed on Invoice"
                        ],
                        "examples": [
                            "Billed on Invoice"
                        ]
                    },
                    "provider": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The payment provider the sale ran on, when the fee is a payment's; null otherwise.",
                        "enum": [
                            "stripe",
                            "paypal",
                            "skrill",
                            "coinpayments",
                            "paystack",
                            "razorpay",
                            "ceypay",
                            "platformcurrency",
                            "accesscode",
                            null
                        ],
                        "examples": [
                            "paypal"
                        ]
                    },
                    "project_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The project the fee was earned on; null for a fee no project carries.",
                        "examples": [
                            "0f1e2d3c-4b5a-4968-8776-655443322110"
                        ]
                    },
                    "project_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "That project's name; null when there is none or it was deleted.",
                        "examples": [
                            "Acme Club"
                        ]
                    },
                    "member_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The member who paid, when the fee is a payment's; null otherwise.",
                        "examples": [
                            "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
                        ]
                    },
                    "member_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "That member's display name; null otherwise.",
                        "examples": [
                            "Jane Fox"
                        ]
                    },
                    "subscription_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The purchase the payment belongs to, when the fee is a payment's; null otherwise.",
                        "examples": [
                            "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
                        ]
                    },
                    "payment_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The payment row the fee was priced from, when there was one; null otherwise.",
                        "examples": [
                            "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b"
                        ]
                    },
                    "gross_amount": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the member paid, as a decimal string in `gross_currency`; null when the fee is not a payment's.",
                        "examples": [
                            "39.0000"
                        ]
                    },
                    "gross_currency": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The ISO 4217 code the member paid in; null when the fee is not a payment's.",
                        "examples": [
                            "USD"
                        ]
                    },
                    "rate_percent": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The percentage applied to the payment, as a decimal string with four places; null when the fee is not a share of a payment.",
                        "examples": [
                            "3.0000"
                        ]
                    },
                    "fee_amount": {
                        "type": "string",
                        "description": "The fee, as a decimal string with four places in `fee_currency`.",
                        "examples": [
                            "1.1700"
                        ]
                    },
                    "fee_currency": {
                        "type": "string",
                        "description": "The ISO 4217 code of the fee: your billing currency.",
                        "examples": [
                            "USD"
                        ]
                    },
                    "units": {
                        "type": "integer",
                        "description": "The cents the usage meter counted for this line; zero on a fee taken at source.",
                        "examples": [
                            117
                        ]
                    },
                    "meter_identifier": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The identifier the meter event carried, when the fee reached the meter outside a payment; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "invoice_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The Subscriby invoice that billed a metered line, once it was paid; null until then and always null on a fee taken at source.",
                        "examples": [
                            "in_1QExampleInvoice00"
                        ]
                    },
                    "invoiced_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When that invoice was paid, ISO 8601; null until then.",
                        "examples": [
                            "2026-11-01T06:30:12+00:00"
                        ]
                    },
                    "occurred_at": {
                        "type": "string",
                        "description": "When the fee was incurred, ISO 8601.",
                        "examples": [
                            "2026-10-14T18:02:41+00:00"
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the line was written, ISO 8601.",
                        "examples": [
                            "2026-10-14T18:02:41+00:00"
                        ]
                    }
                },
                "required": [
                    "id",
                    "kind",
                    "kind_label",
                    "channel",
                    "channel_label",
                    "provider",
                    "project_id",
                    "project_name",
                    "member_id",
                    "member_name",
                    "subscription_id",
                    "payment_id",
                    "gross_amount",
                    "gross_currency",
                    "rate_percent",
                    "fee_amount",
                    "fee_currency",
                    "units",
                    "meter_identifier",
                    "invoice_id",
                    "invoiced_at",
                    "occurred_at",
                    "created_at"
                ],
                "title": "TransactionFeeResource"
            },
            "TransactionFeeSummaryResource": {
                "type": "object",
                "description": "A calendar month of the caller's transaction fees: the totals per channel, the lines per kind and per project, and the Subscriby invoices the metered lines were billed on; the metered total is the figure to hold against the invoice's Transaction Fees line.",
                "properties": {
                    "period_start": {
                        "type": "string",
                        "description": "The first day of the month, ISO 8601 date.",
                        "examples": [
                            "2026-10-01"
                        ]
                    },
                    "period_end": {
                        "type": "string",
                        "description": "The first day of the next month, ISO 8601 date; the window ends before it.",
                        "examples": [
                            "2026-11-01"
                        ]
                    },
                    "currency": {
                        "type": "string",
                        "description": "The ISO 4217 code every amount is in: your billing currency.",
                        "examples": [
                            "USD"
                        ]
                    },
                    "total_fee": {
                        "type": "string",
                        "description": "Every fee of the month, as a decimal string with four places.",
                        "examples": [
                            "48.5100"
                        ]
                    },
                    "at_source_fee": {
                        "type": "string",
                        "description": "The fees Stripe Connect deducted from members' payments; never invoiced.",
                        "examples": [
                            "31.2000"
                        ]
                    },
                    "metered_fee": {
                        "type": "string",
                        "description": "The fees reported to the usage meter, billed or to be billed on your own Subscriby invoice.",
                        "examples": [
                            "17.3100"
                        ]
                    },
                    "metered_units": {
                        "type": "integer",
                        "description": "The cents the meter counted in the month.",
                        "examples": [
                            1731
                        ]
                    },
                    "invoiced_fee": {
                        "type": "string",
                        "description": "The metered fees a paid Subscriby invoice has already collected.",
                        "examples": [
                            "12.4800"
                        ]
                    },
                    "awaiting_invoice_fee": {
                        "type": "string",
                        "description": "The metered fees still waiting for your next invoice.",
                        "examples": [
                            "4.8300"
                        ]
                    },
                    "rows": {
                        "type": "integer",
                        "description": "How many lines the month holds.",
                        "examples": [
                            41
                        ]
                    },
                    "by_kind": {
                        "type": "array",
                        "description": "The month per kind of fee, in catalogue order; a kind with no lines is absent.",
                        "items": {
                            "$ref": "#/components/schemas/TransactionFeeKindShareResource"
                        }
                    },
                    "by_project": {
                        "type": "array",
                        "description": "The month per project, largest first; empty when `project_id` narrowed the summary to one project.",
                        "items": {
                            "$ref": "#/components/schemas/TransactionFeeProjectShareResource"
                        }
                    },
                    "invoices": {
                        "type": "array",
                        "description": "The Subscriby invoices metered lines of the month were billed on, newest first.",
                        "items": {
                            "$ref": "#/components/schemas/TransactionFeeInvoiceResource"
                        }
                    }
                },
                "required": [
                    "period_start",
                    "period_end",
                    "currency",
                    "total_fee",
                    "at_source_fee",
                    "metered_fee",
                    "metered_units",
                    "invoiced_fee",
                    "awaiting_invoice_fee",
                    "rows",
                    "by_kind",
                    "by_project",
                    "invoices"
                ],
                "title": "TransactionFeeSummaryResource"
            },
            "TrialModeType": {
                "type": "string",
                "enum": [
                    "project",
                    "plan"
                ],
                "examples": [
                    "plan"
                ],
                "title": "TrialModeType"
            },
            "UninstallPreviewResource": {
                "type": "object",
                "description": "What uninstalling a connector would touch, nothing changed: the rows beside the counts of them, and the two opt-ins with their defaults.",
                "properties": {
                    "installation": {
                        "type": "array",
                        "description": "The installation that would be uninstalled, in the installation object's shape.",
                        "items": {}
                    },
                    "connector": {
                        "type": "string",
                        "description": "The connector's key.",
                        "examples": [
                            "example"
                        ]
                    },
                    "resources": {
                        "type": "array",
                        "description": "The connector's places on the project; manual perks are never among them. They would be deactivated and marked detached, their external ids kept.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "string",
                                    "description": "The resource's id.",
                                    "examples": [
                                        "b73c5f21-9d80-4a6e-8215-4f70ce13a9d6"
                                    ]
                                },
                                "title": {
                                    "type": "string",
                                    "description": "The resource's title.",
                                    "examples": [
                                        "Members Lounge"
                                    ]
                                },
                                "kind": {
                                    "type": "string",
                                    "description": "The resource's kind, `<connector>:<kind>`.",
                                    "examples": [
                                        "example:role"
                                    ]
                                },
                                "active": {
                                    "type": "boolean",
                                    "description": "Whether the resource is active today.",
                                    "examples": [
                                        true
                                    ]
                                }
                            },
                            "required": [
                                "id",
                                "title",
                                "kind",
                                "active"
                            ]
                        }
                    },
                    "live_grants": {
                        "type": "integer",
                        "description": "The pending, held and granted grants on those places; each would be revoked with reason `connector_uninstalled`, firing `member.resource_removed`.",
                        "examples": [
                            41
                        ],
                        "minimum": 0
                    },
                    "emptied_plans": {
                        "type": "array",
                        "description": "The plans that would keep no active grantable resource.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "string",
                                    "description": "The plan's id.",
                                    "examples": [
                                        "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b"
                                    ]
                                },
                                "name": {
                                    "type": "string",
                                    "description": "The plan's name.",
                                    "examples": [
                                        "Lounge Monthly"
                                    ]
                                },
                                "active": {
                                    "type": "boolean",
                                    "description": "Whether the plan is on sale today.",
                                    "examples": [
                                        true
                                    ]
                                },
                                "recurring": {
                                    "type": "boolean",
                                    "description": "Whether the plan renews, so its live subscriptions could be cancelled by the opt-in.",
                                    "examples": [
                                        true
                                    ]
                                }
                            },
                            "required": [
                                "id",
                                "name",
                                "active",
                                "recurring"
                            ]
                        }
                    },
                    "recurring_subscriptions": {
                        "type": "integer",
                        "description": "How many live recurring purchases sit on the emptied plans.",
                        "examples": [
                            17
                        ],
                        "minimum": 0
                    },
                    "one_time_subscriptions": {
                        "type": "integer",
                        "description": "How many live one-time or lifetime purchases sit on them; these are never cancelled.",
                        "examples": [
                            3
                        ],
                        "minimum": 0
                    },
                    "affected_subscription_ids": {
                        "type": "array",
                        "description": "The ids of every live purchase on the emptied plans.",
                        "items": {
                            "type": "string",
                            "examples": [
                                "5b7e2d40-1a86-4c39-97f2-e83d0b16c5a4"
                            ]
                        }
                    },
                    "upcoming_windows": {
                        "type": "integer",
                        "description": "Informational: pass windows on the connector's places that have not run yet. They are never cancelled for you; cancel them from the pass window endpoints, which handle refunds.",
                        "examples": [
                            0
                        ]
                    },
                    "open_support_threads": {
                        "type": "integer",
                        "description": "Informational: open support threads that would lose their reach.",
                        "examples": [
                            2
                        ]
                    },
                    "member_identities": {
                        "type": "integer",
                        "description": "Informational: member accounts linked on the connector. They are never removed.",
                        "examples": [
                            44
                        ]
                    },
                    "empties_plans": {
                        "type": "boolean",
                        "description": "Whether any plan would be left with nothing to grant.",
                        "examples": [
                            true
                        ]
                    },
                    "options": {
                        "type": "object",
                        "description": "The two opt-ins with their defaults, exactly the names the `DELETE` body takes.",
                        "properties": {
                            "unpublish_emptied_plans": {
                                "type": "boolean",
                                "description": "Whether the emptied plans would be taken off sale; on by default.",
                                "examples": [
                                    true
                                ]
                            },
                            "cancel_recurring_subscriptions": {
                                "type": "boolean",
                                "description": "Whether their live recurring subscriptions would be cancelled at the end of the paid period; on by default.",
                                "examples": [
                                    true
                                ]
                            }
                        },
                        "required": [
                            "unpublish_emptied_plans",
                            "cancel_recurring_subscriptions"
                        ]
                    }
                },
                "required": [
                    "installation",
                    "connector",
                    "resources",
                    "live_grants",
                    "emptied_plans",
                    "recurring_subscriptions",
                    "one_time_subscriptions",
                    "affected_subscription_ids",
                    "upcoming_windows",
                    "open_support_threads",
                    "member_identities",
                    "empties_plans",
                    "options"
                ],
                "title": "UninstallPreviewResource"
            },
            "UninstallReportResource": {
                "type": "object",
                "description": "What an uninstall did: the same numbers the `connector.uninstalled` event carries, beside the installation as it stands afterwards.",
                "properties": {
                    "installation": {
                        "type": "array",
                        "description": "The installation as it stands afterwards, `disconnected` with `uninstalled_at` set, in the installation object's shape.",
                        "items": {}
                    },
                    "connector": {
                        "type": "string",
                        "description": "The connector's key.",
                        "examples": [
                            "example"
                        ]
                    },
                    "grants_revoked": {
                        "type": "integer",
                        "description": "How many grants were revoked.",
                        "examples": [
                            41
                        ]
                    },
                    "resources_detached": {
                        "type": "integer",
                        "description": "How many places were detached.",
                        "examples": [
                            2
                        ]
                    },
                    "plans_unpublished": {
                        "type": "integer",
                        "description": "How many emptied plans were taken off sale by the opt-in.",
                        "examples": [
                            1
                        ]
                    },
                    "subscriptions_cancelled": {
                        "type": "integer",
                        "description": "How many recurring subscriptions were cancelled at the end of their paid period by the opt-in.",
                        "examples": [
                            0
                        ]
                    },
                    "members_notified": {
                        "type": "integer",
                        "description": "How many members were emailed that their subscription will not renew.",
                        "examples": [
                            0
                        ]
                    }
                },
                "required": [
                    "installation",
                    "connector",
                    "grants_revoked",
                    "resources_detached",
                    "plans_unpublished",
                    "subscriptions_cancelled",
                    "members_notified"
                ],
                "title": "UninstallReportResource"
            },
            "UpdateAlertDestinationsRequest": {
                "type": "object",
                "description": "The complete set of alert destinations to keep. Anything not listed is removed; an empty list returns you to the default routing.",
                "properties": {
                    "destinations": {
                        "type": "array",
                        "description": "Every destination you want, at most 20. The key must be present; an empty list removes every row and restores the default.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "kind": {
                                    "description": "`connector_identity` for a connected account or `email` for an address.",
                                    "$ref": "#/components/schemas/AlertDestinationKind"
                                },
                                "target": {
                                    "type": "string",
                                    "description": "The connected account's id or the email address. It must be one of your own linked accounts or your own address; anything else is refused with `404 RESOURCE_NOT_FOUND` and nothing is written.",
                                    "maxLength": 255
                                },
                                "classes": {
                                    "type": [
                                        "array",
                                        "null"
                                    ],
                                    "description": "The alert classes to route here, any of `sales`, `support`, `recovery`, `billing`, `security`, `passes`, `onboarding`. Send `null` for every class or `[]` for none. `is_primary` is not accepted; the service derives it.",
                                    "items": {
                                        "description": "An alert class.",
                                        "$ref": "#/components/schemas/AlertClass"
                                    }
                                }
                            },
                            "required": [
                                "kind",
                                "target"
                            ]
                        },
                        "maxItems": 20
                    }
                },
                "required": [
                    "destinations"
                ],
                "title": "UpdateAlertDestinationsRequest"
            },
            "UpdateCopilotCreditSettingsRequest": {
                "type": "object",
                "description": "Validates PATCH /api/v1/me/copilot-credits/settings: the auto top-up and the monthly cap.\n\nPartial by design: every field is optional and an omitted one keeps its\nstored value, so a client can switch the auto top-up off with one key.\nThe bounds are the Billing dialog's, in cents: a threshold of $1 to $100\nand a cap of $0 to $10,000, so the API cannot set what the dialog refuses.",
                "properties": {
                    "auto_topup_pack": {
                        "description": "The pack the auto top-up buys when the balance falls under the threshold, one of the packs on sale; null switches the auto top-up off. Switching it on needs a card on file.",
                        "anyOf": [
                            {
                                "$ref": "#/components/schemas/CopilotCreditPack"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "auto_topup_below_cents": {
                        "type": "integer",
                        "description": "The balance under which the auto top-up buys, 100 to 10,000 (US cents).",
                        "minimum": 100,
                        "maximum": 10000
                    },
                    "monthly_spend_cap_cents": {
                        "type": "integer",
                        "description": "The paid credit the Copilot may draw in a calendar month before it stops, 0 to 1,000,000 (US cents); the free allowance is never capped.",
                        "minimum": 0,
                        "maximum": 1000000
                    }
                },
                "title": "UpdateCopilotCreditSettingsRequest"
            },
            "UpdateCouponRequest": {
                "type": "object",
                "description": "The changes to a coupon: any subset of the create shape. A change is never retroactive; subscribers who already redeemed keep exactly what they paid.",
                "properties": {
                    "code": {
                        "type": "string",
                        "description": "A new code, 3 to 64 letters, numbers and dashes, uppercased before the uniqueness check against the project's other live coupons.",
                        "pattern": "^[A-Za-z0-9-]+$",
                        "minLength": 3,
                        "maxLength": 64
                    },
                    "name": {
                        "type": "string",
                        "description": "A new creator-facing label, 3 to 255 characters.",
                        "minLength": 3,
                        "maxLength": 255
                    },
                    "discount_type": {
                        "description": "`percentage` or `fixed`.",
                        "$ref": "#/components/schemas/CouponDiscountType"
                    },
                    "discount_value": {
                        "type": "number",
                        "description": "Greater than 0; at most 100 when the coupon is, or becomes, a percentage."
                    },
                    "currency_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Required when the coupon is, or becomes, `fixed` and it has no currency yet; refused as meaningless on a percentage coupon."
                    },
                    "duration": {
                        "type": "string",
                        "description": "Accepted for forward compatibility but only `once` is honoured.",
                        "enum": [
                            "once"
                        ]
                    },
                    "max_redemptions": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The new total cap, 1 to 1,000,000, or null for unlimited. Raising it on an exhausted coupon makes it redeemable again; lowering it below the current count claws nothing back, the coupon simply reports `remaining: 0`.",
                        "minimum": 1,
                        "maximum": 1000000
                    },
                    "max_redemptions_per_user": {
                        "type": "integer",
                        "description": "How many times one member may redeem the code, 1 to 1,000.",
                        "minimum": 1,
                        "maximum": 1000
                    },
                    "minimum_amount": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "The order floor, in the plan's own currency; greater than 0, or null for none."
                    },
                    "starts_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When redemption opens, ISO 8601, or null for immediately."
                    },
                    "expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When redemption closes, ISO 8601, or null for never."
                    },
                    "active": {
                        "type": "boolean",
                        "description": "The on/off switch; prefer the activate and deactivate endpoints, which fire their own events."
                    },
                    "plan_ids": {
                        "type": "array",
                        "description": "The plans to restrict the code to, at most 200; `[]` opens it to every plan.",
                        "items": {
                            "type": "string",
                            "description": "A plan id of this project."
                        },
                        "maxItems": 200
                    }
                },
                "title": "UpdateCouponRequest"
            },
            "UpdateInstallationSettingsRequest": {
                "type": "object",
                "description": "The settings and capability switches to change on an installation. At least one of the two is required; keys left out keep their value.",
                "properties": {
                    "settings": {
                        "type": "array",
                        "description": "An object keyed by the field names the connector declares in its `settings_fields` (read them from the connector's card). Every declared rule runs; a key the connector never declared is `422 VALIDATION_FAILED` naming it.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "capabilities": {
                        "type": "array",
                        "description": "An object keyed by capability to `true` or `false`: the project's switches for what the connector may do on this installation. A capability the connector does not declare, or one that cannot be switched off (`access_control`, `early_admission_hold`, `management_surface`, `portal_login`, `creator_registration`), is `422 VALIDATION_FAILED` naming it.",
                        "items": {
                            "type": "boolean"
                        }
                    }
                },
                "title": "UpdateInstallationSettingsRequest"
            },
            "UpdateKnowledgeEntryRequest": {
                "type": "object",
                "description": "The changes to a Knowledge entry. Every field is optional and an omitted one keeps its stored value; the kind never changes.",
                "properties": {
                    "title": {
                        "type": "string",
                        "description": "The question, or the document's name, 2 to 160 characters.",
                        "minLength": 2,
                        "maxLength": 160
                    },
                    "body": {
                        "type": "string",
                        "description": "The answer, or the document's text, 2 to 50,000 characters; new words are cut into passages again in the same step.",
                        "minLength": 2,
                        "maxLength": 50000
                    },
                    "audience": {
                        "description": "`members` or `team`; a change retags the passages without rewriting them.",
                        "$ref": "#/components/schemas/KnowledgeAudience"
                    }
                },
                "title": "UpdateKnowledgeEntryRequest"
            },
            "UpdatePartnerPayoutDetailsRequest": {
                "type": "object",
                "description": "The rail to be paid by, what it pays to, and the tax declaration. Only the destination the chosen rail uses is kept; a rail left behind keeps nothing on file.",
                "properties": {
                    "method": {
                        "description": "The rail: `credit` (Subscriby Credit applied to your own invoices, while the rail is open), `paypal`, `wise`, `remitly` or `crypto` (USDT on TRC20).",
                        "$ref": "#/components/schemas/PartnerPayoutMethod"
                    },
                    "details": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What a single-detail rail pays to: the PayPal email for `paypal`, the wallet address for `crypto`. Required on those rails, ignored on the others. At most 190 characters.",
                        "maxLength": 190
                    },
                    "bank_holder": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The name on the bank account, for `wise` and `remitly`. At most 120 characters.",
                        "maxLength": 120
                    },
                    "bank_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The bank, for `wise` and `remitly`. At most 120 characters.",
                        "maxLength": 120
                    },
                    "bank_country": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Where the bank is, as an ISO 3166-1 alpha-2 code, for `wise` and `remitly`.",
                        "minLength": 2,
                        "maxLength": 2
                    },
                    "bank_account_number": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The account number or IBAN, for `wise` and `remitly`: letters, digits, spaces and dashes, at most 40 characters.",
                        "pattern": "^[A-Za-z0-9 -]+$",
                        "maxLength": 40
                    },
                    "bank_swift": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The SWIFT or BIC code, when the bank has one: 8 or 11 characters.",
                        "pattern": "^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$"
                    },
                    "bank_branch_code": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The branch, routing, sort or IFSC code, when the transfer needs one: letters, digits, spaces and dashes, at most 20 characters.",
                        "pattern": "^[A-Za-z0-9 -]+$",
                        "maxLength": 20
                    },
                    "bank_address": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The account holder's address, when the transfer needs one. At most 200 characters.",
                        "maxLength": 200
                    },
                    "legal_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The name a payment is made out to. Required on every cash rail. At most 120 characters.",
                        "maxLength": 120
                    },
                    "tax_country": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The country of tax residence, as an ISO 3166-1 alpha-2 code. Required on every cash rail.",
                        "minLength": 2,
                        "maxLength": 2
                    },
                    "us_person": {
                        "type": [
                            "boolean",
                            "null"
                        ],
                        "description": "Whether you are a US person for tax purposes."
                    },
                    "accept_terms": {
                        "type": "boolean",
                        "description": "Send `true` to accept the Partner Program Terms with this save. A rail cannot be saved until the terms are accepted, here or through the terms endpoint."
                    }
                },
                "required": [
                    "method"
                ],
                "title": "UpdatePartnerPayoutDetailsRequest"
            },
            "UpdatePlanRequest": {
                "type": "object",
                "description": "The changes to a plan: any subset of the create shape. A block must match the plan's kind, and a field left out keeps its stored value.",
                "properties": {
                    "kind": {
                        "description": "`subscription`, `pass` or `pass_series`; names the one block the payload carries. Required on create. Omit on an update to keep the plan's current kind.\n| |\n|---|\n| `subscription` <br/> Access starts at payment and runs on a billing cycle. |\n| `pass` <br/> One purchase buys one of the plan's own scheduled access windows. |\n| `pass_series` <br/> One purchase buys a curated slate of *other* plans' access windows. |",
                        "$ref": "#/components/schemas/PlanKind"
                    },
                    "name": {
                        "type": "string",
                        "description": "The name buyers see, 5 to 255 characters, unique within the project without regard to case or surrounding spaces. Required on create.",
                        "minLength": 5,
                        "maxLength": 255
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The pitch under the name, up to 1,000 characters. HTML is filtered to a safe subset before it is stored.",
                        "maxLength": 1000
                    },
                    "currency_id": {
                        "type": "string",
                        "description": "The id of a currency that at least one of the project's active payment methods can charge. Required on create."
                    },
                    "price": {
                        "type": "number",
                        "description": "What one purchase costs: at least the $1.00 USD equivalent in `currency_id` at the current rate, or exactly `0` for a free plan, which only a Starter or Growth account may put on sale. Required on create.",
                        "minimum": 0
                    },
                    "active": {
                        "type": "boolean",
                        "description": "Whether the plan is on sale. Defaults to true on create; prefer the publish and unpublish endpoints to change it later."
                    },
                    "sales_cap": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Pause the plan after this many purchases, 1 to 100,000; null for no limit. Changing it restarts `sales_cap_sold` at 0.",
                        "minimum": 1,
                        "maximum": 100000
                    },
                    "eligibility": {
                        "type": "object",
                        "description": "Who may buy. At most one of the first three may be true, counting what the plan already holds on an update.",
                        "properties": {
                            "newcomers_only": {
                                "type": "boolean",
                                "description": "Only members who never held a subscription on the project."
                            },
                            "customers_only": {
                                "type": "boolean",
                                "description": "Only members who currently hold one."
                            },
                            "churned_only": {
                                "type": "boolean",
                                "description": "Only members who held one and let it lapse."
                            },
                            "single_use": {
                                "type": "boolean",
                                "description": "Each member may buy the plan once."
                            },
                            "access_codes_only": {
                                "type": "boolean",
                                "description": "The plan cannot be bought, only granted by redeeming an access code."
                            }
                        }
                    },
                    "resources": {
                        "type": "array",
                        "description": "Ids of the project's resources the plan grants: at least one, required on create, except on `kind: pass_series`, where it is optional and names a lounge open for the whole span. Omit on an update to keep the existing links.",
                        "items": {
                            "type": "string",
                            "description": "A resource id."
                        },
                        "minItems": 1
                    },
                    "billing": {
                        "type": "object",
                        "description": "Cycle, trial and renewal. Send it on `kind: subscription` only; on any other kind it is refused.",
                        "properties": {
                            "billing_cycle": {
                                "description": "`day`, `week`, `month`, `year` or `lifetime`. Required on create.",
                                "$ref": "#/components/schemas/SubscriptionBillingCycle"
                            },
                            "billing_cycle_count": {
                                "type": "integer",
                                "description": "How many cycles one period spans, 1 to 99; must be 1 when the cycle is `lifetime`. Required on create.",
                                "minimum": 1,
                                "maximum": 99
                            },
                            "recurring": {
                                "type": "boolean",
                                "description": "Whether the subscription renews itself. Refused as true when the currency is a crypto or platform currency."
                            },
                            "disabled_renewal": {
                                "type": "boolean",
                                "description": "Charge once, then lapse at the end of the period instead of renewing."
                            },
                            "trial_days": {
                                "type": "integer",
                                "description": "Free days before the first charge, 0 to 365.",
                                "minimum": 0,
                                "maximum": 365
                            },
                            "trial_cardless": {
                                "type": "boolean",
                                "description": "Whether the trial starts without a payment method on file."
                            },
                            "trial_type": {
                                "description": "Whose trial rule applies: `project` uses the project's trial settings, `plan` this plan's own.",
                                "$ref": "#/components/schemas/TrialModeType"
                            }
                        }
                    },
                    "pass": {
                        "type": "object",
                        "description": "The plan's own dated schedule. Send it on `kind: pass` only; on any other kind it is refused.",
                        "properties": {
                            "timezone": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The IANA zone the schedule is authored in. Legacy names are resolved, so `Asia/Calcutta` is stored as `Asia/Kolkata`. Required on create.",
                                "enum": [
                                    "GMT",
                                    "UTC",
                                    "Africa/Abidjan",
                                    "Africa/Accra",
                                    "Africa/Bamako",
                                    "Africa/Banjul",
                                    "Africa/Bissau",
                                    "Africa/Casablanca",
                                    "Africa/Conakry",
                                    "Africa/Dakar",
                                    "Africa/El_Aaiun",
                                    "Africa/Freetown",
                                    "Africa/Lome",
                                    "Africa/Monrovia",
                                    "Africa/Nouakchott",
                                    "Africa/Ouagadougou",
                                    "Africa/Sao_Tome",
                                    "Africa/Algiers",
                                    "Africa/Bangui",
                                    "Africa/Brazzaville",
                                    "Africa/Ceuta",
                                    "Africa/Douala",
                                    "Africa/Kinshasa",
                                    "Africa/Lagos",
                                    "Africa/Libreville",
                                    "Africa/Luanda",
                                    "Africa/Malabo",
                                    "Africa/Ndjamena",
                                    "Africa/Niamey",
                                    "Africa/Porto-Novo",
                                    "Africa/Tunis",
                                    "Africa/Blantyre",
                                    "Africa/Bujumbura",
                                    "Africa/Cairo",
                                    "Africa/Gaborone",
                                    "Africa/Harare",
                                    "Africa/Johannesburg",
                                    "Africa/Juba",
                                    "Africa/Khartoum",
                                    "Africa/Kigali",
                                    "Africa/Lubumbashi",
                                    "Africa/Lusaka",
                                    "Africa/Maputo",
                                    "Africa/Maseru",
                                    "Africa/Mbabane",
                                    "Africa/Tripoli",
                                    "Africa/Windhoek",
                                    "Africa/Addis_Ababa",
                                    "Africa/Asmara",
                                    "Africa/Dar_es_Salaam",
                                    "Africa/Djibouti",
                                    "Africa/Kampala",
                                    "Africa/Mogadishu",
                                    "Africa/Nairobi",
                                    "America/Adak",
                                    "America/Anchorage",
                                    "America/Juneau",
                                    "America/Metlakatla",
                                    "America/Nome",
                                    "America/Sitka",
                                    "America/Yakutat",
                                    "America/Los_Angeles",
                                    "America/Tijuana",
                                    "America/Boise",
                                    "America/Cambridge_Bay",
                                    "America/Ciudad_Juarez",
                                    "America/Creston",
                                    "America/Dawson",
                                    "America/Dawson_Creek",
                                    "America/Denver",
                                    "America/Fort_Nelson",
                                    "America/Hermosillo",
                                    "America/Mazatlan",
                                    "America/Phoenix",
                                    "America/Vancouver",
                                    "America/Whitehorse",
                                    "America/Bahia_Banderas",
                                    "America/Belize",
                                    "America/Chicago",
                                    "America/Chihuahua",
                                    "America/Costa_Rica",
                                    "America/Edmonton",
                                    "America/El_Salvador",
                                    "America/Guatemala",
                                    "America/Indiana/Knox",
                                    "America/Indiana/Tell_City",
                                    "America/Inuvik",
                                    "America/Managua",
                                    "America/Matamoros",
                                    "America/Menominee",
                                    "America/Merida",
                                    "America/Mexico_City",
                                    "America/Monterrey",
                                    "America/North_Dakota/Beulah",
                                    "America/North_Dakota/Center",
                                    "America/North_Dakota/New_Salem",
                                    "America/Ojinaga",
                                    "America/Rankin_Inlet",
                                    "America/Regina",
                                    "America/Resolute",
                                    "America/Swift_Current",
                                    "America/Tegucigalpa",
                                    "America/Atikokan",
                                    "America/Bogota",
                                    "America/Cancun",
                                    "America/Cayman",
                                    "America/Detroit",
                                    "America/Eirunepe",
                                    "America/Grand_Turk",
                                    "America/Guayaquil",
                                    "America/Havana",
                                    "America/Indiana/Indianapolis",
                                    "America/Indiana/Marengo",
                                    "America/Indiana/Petersburg",
                                    "America/Indiana/Vevay",
                                    "America/Indiana/Vincennes",
                                    "America/Indiana/Winamac",
                                    "America/Iqaluit",
                                    "America/Jamaica",
                                    "America/Kentucky/Louisville",
                                    "America/Kentucky/Monticello",
                                    "America/Lima",
                                    "America/Nassau",
                                    "America/New_York",
                                    "America/Panama",
                                    "America/Port-au-Prince",
                                    "America/Rio_Branco",
                                    "America/Toronto",
                                    "America/Winnipeg",
                                    "America/Anguilla",
                                    "America/Antigua",
                                    "America/Aruba",
                                    "America/Barbados",
                                    "America/Blanc-Sablon",
                                    "America/Boa_Vista",
                                    "America/Campo_Grande",
                                    "America/Caracas",
                                    "America/Cuiaba",
                                    "America/Curacao",
                                    "America/Dominica",
                                    "America/Glace_Bay",
                                    "America/Goose_Bay",
                                    "America/Grenada",
                                    "America/Guadeloupe",
                                    "America/Guyana",
                                    "America/Halifax",
                                    "America/Kralendijk",
                                    "America/La_Paz",
                                    "America/Lower_Princes",
                                    "America/Manaus",
                                    "America/Marigot",
                                    "America/Martinique",
                                    "America/Moncton",
                                    "America/Montserrat",
                                    "America/Port_of_Spain",
                                    "America/Porto_Velho",
                                    "America/Puerto_Rico",
                                    "America/Santo_Domingo",
                                    "America/St_Barthelemy",
                                    "America/St_Kitts",
                                    "America/St_Lucia",
                                    "America/St_Thomas",
                                    "America/St_Vincent",
                                    "America/Thule",
                                    "America/Tortola",
                                    "America/St_Johns",
                                    "America/Araguaina",
                                    "America/Argentina/Buenos_Aires",
                                    "America/Argentina/Catamarca",
                                    "America/Argentina/Cordoba",
                                    "America/Argentina/Jujuy",
                                    "America/Argentina/La_Rioja",
                                    "America/Argentina/Mendoza",
                                    "America/Argentina/Rio_Gallegos",
                                    "America/Argentina/Salta",
                                    "America/Argentina/San_Juan",
                                    "America/Argentina/San_Luis",
                                    "America/Argentina/Tucuman",
                                    "America/Argentina/Ushuaia",
                                    "America/Asuncion",
                                    "America/Bahia",
                                    "America/Belem",
                                    "America/Cayenne",
                                    "America/Coyhaique",
                                    "America/Fortaleza",
                                    "America/Maceio",
                                    "America/Miquelon",
                                    "America/Montevideo",
                                    "America/Paramaribo",
                                    "America/Punta_Arenas",
                                    "America/Recife",
                                    "America/Santarem",
                                    "America/Santiago",
                                    "America/Sao_Paulo",
                                    "America/Noronha",
                                    "America/Nuuk",
                                    "America/Scoresbysund",
                                    "America/Danmarkshavn",
                                    "Antarctica/Palmer",
                                    "Antarctica/Rothera",
                                    "Antarctica/Troll",
                                    "Antarctica/Syowa",
                                    "Antarctica/Mawson",
                                    "Antarctica/Vostok",
                                    "Antarctica/Davis",
                                    "Antarctica/Casey",
                                    "Antarctica/DumontDUrville",
                                    "Antarctica/Macquarie",
                                    "Antarctica/McMurdo",
                                    "Arctic/Longyearbyen",
                                    "Asia/Beirut",
                                    "Asia/Famagusta",
                                    "Asia/Gaza",
                                    "Asia/Hebron",
                                    "Asia/Jerusalem",
                                    "Asia/Nicosia",
                                    "Asia/Aden",
                                    "Asia/Amman",
                                    "Asia/Baghdad",
                                    "Asia/Bahrain",
                                    "Asia/Damascus",
                                    "Asia/Kuwait",
                                    "Asia/Qatar",
                                    "Asia/Riyadh",
                                    "Asia/Tehran",
                                    "Asia/Baku",
                                    "Asia/Dubai",
                                    "Asia/Muscat",
                                    "Asia/Tbilisi",
                                    "Asia/Yerevan",
                                    "Asia/Kabul",
                                    "Asia/Almaty",
                                    "Asia/Aqtau",
                                    "Asia/Aqtobe",
                                    "Asia/Ashgabat",
                                    "Asia/Atyrau",
                                    "Asia/Dushanbe",
                                    "Asia/Karachi",
                                    "Asia/Oral",
                                    "Asia/Qostanay",
                                    "Asia/Qyzylorda",
                                    "Asia/Samarkand",
                                    "Asia/Tashkent",
                                    "Asia/Yekaterinburg",
                                    "Asia/Colombo",
                                    "Asia/Kolkata",
                                    "Asia/Kathmandu",
                                    "Asia/Bishkek",
                                    "Asia/Dhaka",
                                    "Asia/Omsk",
                                    "Asia/Thimphu",
                                    "Asia/Urumqi",
                                    "Asia/Yangon",
                                    "Asia/Bangkok",
                                    "Asia/Barnaul",
                                    "Asia/Ho_Chi_Minh",
                                    "Asia/Hovd",
                                    "Asia/Jakarta",
                                    "Asia/Krasnoyarsk",
                                    "Asia/Novokuznetsk",
                                    "Asia/Novosibirsk",
                                    "Asia/Phnom_Penh",
                                    "Asia/Pontianak",
                                    "Asia/Tomsk",
                                    "Asia/Vientiane",
                                    "Asia/Brunei",
                                    "Asia/Hong_Kong",
                                    "Asia/Irkutsk",
                                    "Asia/Kuala_Lumpur",
                                    "Asia/Kuching",
                                    "Asia/Macau",
                                    "Asia/Makassar",
                                    "Asia/Manila",
                                    "Asia/Shanghai",
                                    "Asia/Singapore",
                                    "Asia/Taipei",
                                    "Asia/Ulaanbaatar",
                                    "Asia/Chita",
                                    "Asia/Dili",
                                    "Asia/Jayapura",
                                    "Asia/Khandyga",
                                    "Asia/Pyongyang",
                                    "Asia/Seoul",
                                    "Asia/Tokyo",
                                    "Asia/Yakutsk",
                                    "Asia/Ust-Nera",
                                    "Asia/Vladivostok",
                                    "Asia/Magadan",
                                    "Asia/Sakhalin",
                                    "Asia/Srednekolymsk",
                                    "Asia/Anadyr",
                                    "Asia/Kamchatka",
                                    "Atlantic/Bermuda",
                                    "Atlantic/Stanley",
                                    "Atlantic/South_Georgia",
                                    "Atlantic/Azores",
                                    "Atlantic/Cape_Verde",
                                    "Atlantic/Canary",
                                    "Atlantic/Faroe",
                                    "Atlantic/Madeira",
                                    "Atlantic/Reykjavik",
                                    "Atlantic/St_Helena",
                                    "Australia/Perth",
                                    "Australia/Eucla",
                                    "Australia/Darwin",
                                    "Australia/Brisbane",
                                    "Australia/Lindeman",
                                    "Australia/Adelaide",
                                    "Australia/Broken_Hill",
                                    "Australia/Hobart",
                                    "Australia/Lord_Howe",
                                    "Australia/Melbourne",
                                    "Australia/Sydney",
                                    "Europe/Dublin",
                                    "Europe/Guernsey",
                                    "Europe/Isle_of_Man",
                                    "Europe/Jersey",
                                    "Europe/Lisbon",
                                    "Europe/London",
                                    "Europe/Amsterdam",
                                    "Europe/Andorra",
                                    "Europe/Belgrade",
                                    "Europe/Berlin",
                                    "Europe/Bratislava",
                                    "Europe/Brussels",
                                    "Europe/Budapest",
                                    "Europe/Busingen",
                                    "Europe/Copenhagen",
                                    "Europe/Gibraltar",
                                    "Europe/Ljubljana",
                                    "Europe/Luxembourg",
                                    "Europe/Madrid",
                                    "Europe/Malta",
                                    "Europe/Monaco",
                                    "Europe/Oslo",
                                    "Europe/Paris",
                                    "Europe/Podgorica",
                                    "Europe/Prague",
                                    "Europe/Rome",
                                    "Europe/San_Marino",
                                    "Europe/Sarajevo",
                                    "Europe/Skopje",
                                    "Europe/Stockholm",
                                    "Europe/Tirane",
                                    "Europe/Vaduz",
                                    "Europe/Vatican",
                                    "Europe/Vienna",
                                    "Europe/Warsaw",
                                    "Europe/Zagreb",
                                    "Europe/Zurich",
                                    "Europe/Athens",
                                    "Europe/Bucharest",
                                    "Europe/Chisinau",
                                    "Europe/Helsinki",
                                    "Europe/Kaliningrad",
                                    "Europe/Kyiv",
                                    "Europe/Mariehamn",
                                    "Europe/Riga",
                                    "Europe/Sofia",
                                    "Europe/Tallinn",
                                    "Europe/Vilnius",
                                    "Europe/Istanbul",
                                    "Europe/Kirov",
                                    "Europe/Minsk",
                                    "Europe/Moscow",
                                    "Europe/Simferopol",
                                    "Europe/Volgograd",
                                    "Europe/Astrakhan",
                                    "Europe/Samara",
                                    "Europe/Saratov",
                                    "Europe/Ulyanovsk",
                                    "Indian/Antananarivo",
                                    "Indian/Comoro",
                                    "Indian/Mayotte",
                                    "Indian/Mahe",
                                    "Indian/Mauritius",
                                    "Indian/Reunion",
                                    "Indian/Kerguelen",
                                    "Indian/Maldives",
                                    "Indian/Chagos",
                                    "Indian/Cocos",
                                    "Indian/Christmas",
                                    "Pacific/Midway",
                                    "Pacific/Niue",
                                    "Pacific/Pago_Pago",
                                    "Pacific/Honolulu",
                                    "Pacific/Rarotonga",
                                    "Pacific/Tahiti",
                                    "Pacific/Marquesas",
                                    "Pacific/Gambier",
                                    "Pacific/Pitcairn",
                                    "Pacific/Galapagos",
                                    "Pacific/Easter",
                                    "Pacific/Palau",
                                    "Pacific/Chuuk",
                                    "Pacific/Guam",
                                    "Pacific/Port_Moresby",
                                    "Pacific/Saipan",
                                    "Pacific/Bougainville",
                                    "Pacific/Efate",
                                    "Pacific/Guadalcanal",
                                    "Pacific/Kosrae",
                                    "Pacific/Noumea",
                                    "Pacific/Pohnpei",
                                    "Pacific/Fiji",
                                    "Pacific/Funafuti",
                                    "Pacific/Kwajalein",
                                    "Pacific/Majuro",
                                    "Pacific/Nauru",
                                    "Pacific/Norfolk",
                                    "Pacific/Tarawa",
                                    "Pacific/Wake",
                                    "Pacific/Wallis",
                                    "Pacific/Apia",
                                    "Pacific/Auckland",
                                    "Pacific/Fakaofo",
                                    "Pacific/Kanton",
                                    "Pacific/Tongatapu",
                                    "Pacific/Chatham",
                                    "Pacific/Kiritimati",
                                    null
                                ]
                            },
                            "schedule_mode": {
                                "description": "`repeating` (the default) generates windows from `slots`; `fixed` takes explicitly dated `windows`.",
                                "anyOf": [
                                    {
                                        "$ref": "#/components/schemas/PassScheduleMode"
                                    },
                                    {
                                        "type": "null"
                                    }
                                ]
                            },
                            "recurrence": {
                                "description": "`daily`, `weekly` or `monthly`. Decides which slot fields apply.",
                                "anyOf": [
                                    {
                                        "$ref": "#/components/schemas/PassRecurrence"
                                    },
                                    {
                                        "type": "null"
                                    }
                                ]
                            },
                            "recurrence_ends_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "format": "date-time",
                                "description": "When window generation stops; omit to keep generating."
                            },
                            "sales_cutoff_minutes": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "Stop sales this many minutes before the moment `sales_cutoff_anchor` names; omit to sell until the window begins. With `before_end` it must be at least 5 and under the shortest slot's `duration_minutes`.",
                                "minimum": 0
                            },
                            "sales_cutoff_anchor": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "`before_start` (the default) or `before_end`. `before_end` is refused when the shortest slot lasts 5 minutes or less. The series anchors `before_first_end` and `before_last_start` are refused on a pass.",
                                "enum": [
                                    "before_start",
                                    "before_end",
                                    null
                                ]
                            },
                            "slots": {
                                "type": "array",
                                "description": "The repeating schedule, at most 60 slots. Sending it replaces the whole schedule and rebuilds unsold future windows; windows a customer has bought keep their times.",
                                "items": {
                                    "type": "object",
                                    "properties": {
                                        "weekday": {
                                            "type": [
                                                "integer",
                                                "null"
                                            ],
                                            "description": "Day of the week, 0 (Sunday) to 6, on a weekly recurrence.",
                                            "minimum": 0,
                                            "maximum": 6
                                        },
                                        "day_of_month": {
                                            "type": [
                                                "integer",
                                                "null"
                                            ],
                                            "description": "Day of the month, 1 to 31, on a monthly recurrence; 29 to 31 skip the months that lack the day.",
                                            "minimum": 1,
                                            "maximum": 31
                                        },
                                        "start_time": {
                                            "type": "string",
                                            "description": "Local wall-clock start in `pass.timezone`, `HH:MM`."
                                        },
                                        "duration_minutes": {
                                            "type": "integer",
                                            "description": "How long the window stays open.",
                                            "minimum": 5,
                                            "maximum": 43200
                                        }
                                    }
                                },
                                "maxItems": 60
                            },
                            "windows": {
                                "type": "array",
                                "description": "Explicitly dated windows for `schedule_mode: fixed`, at most 200 per call. Added to the schedule, never replacing it.",
                                "items": {
                                    "type": "object",
                                    "properties": {
                                        "starts_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "description": "Local wall-clock start in `pass.timezone`."
                                        },
                                        "duration_minutes": {
                                            "type": "integer",
                                            "description": "How long the window stays open.",
                                            "minimum": 5,
                                            "maximum": 43200
                                        }
                                    }
                                },
                                "maxItems": 200
                            }
                        }
                    },
                    "pass_series": {
                        "type": "object",
                        "description": "The season ticket's slate, rules and seats. Send it on `kind: pass_series` only; on any other kind it is refused.",
                        "properties": {
                            "prevent_overlaps": {
                                "type": "boolean",
                                "description": "Refuse a window that clashes with one already on the slate. Defaults to true."
                            },
                            "sales_cutoff_minutes": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "Stop sales this many minutes before the moment `sales_cutoff_anchor` names, measured against the whole season.",
                                "minimum": 0
                            },
                            "sales_cutoff_anchor": {
                                "description": "`before_start` (the default), `before_first_end`, `before_last_start` or `before_end`. `before_first_end` needs `sales_cutoff_minutes` of at least 5, so a buyer arriving late in the opening window is still admitted to it.",
                                "anyOf": [
                                    {
                                        "$ref": "#/components/schemas/PassSalesCutoffAnchor"
                                    },
                                    {
                                        "type": "null"
                                    }
                                ]
                            },
                            "seat_cap": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "How many holders may hold the season at once, at least 1; null for unlimited. Zero is refused: take the plan off sale with unpublish instead.",
                                "minimum": 1
                            },
                            "presale_hours": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "How long the next season is offered to current holders only, 1 to 8760.",
                                "minimum": 1,
                                "maximum": 8760
                            },
                            "successor_plan_id": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Another `kind: pass_series` plan on the same project to offer holders when this one finishes. A series cannot lead to itself."
                            },
                            "window_ids": {
                                "type": "array",
                                "description": "Ids of pass windows on this project to put on the slate, at most 120. A slate needs at least two unless a rule will supply them; with `prevent_overlaps` on, two that run at the same time are refused.",
                                "items": {
                                    "type": "string",
                                    "description": "A pass window id."
                                },
                                "maxItems": 120
                            },
                            "blackout_window_ids": {
                                "type": "array",
                                "description": "Windows a rule matches but you want permanently excluded.",
                                "items": {
                                    "type": "string",
                                    "description": "A pass window id."
                                }
                            },
                            "rules": {
                                "type": "array",
                                "description": "Rules that keep absorbing matching windows into the slate, at most 20. A matching window scheduled later is added and granted to every current holder at no charge.",
                                "items": {
                                    "type": "object",
                                    "properties": {
                                        "source_plan_id": {
                                            "type": "string",
                                            "description": "A `kind: pass` plan on this project to draw windows from."
                                        },
                                        "kind": {
                                            "description": "`date_range` takes every window between `from_at` and `to_at`; `next_n` takes the next `take` windows.\n| |\n|---|\n| `date_range` <br/> Every window of the source plan that starts between two dates. |\n| `next_n` <br/> The next N windows of the source plan, whenever they fall. |",
                                            "$ref": "#/components/schemas/SeriesRuleKind"
                                        },
                                        "from_at": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "format": "date-time",
                                            "description": "The earliest window start a `date_range` rule takes."
                                        },
                                        "to_at": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "format": "date-time",
                                            "description": "The latest window start a `date_range` rule takes."
                                        },
                                        "take": {
                                            "type": [
                                                "integer",
                                                "null"
                                            ],
                                            "description": "How many windows a `next_n` rule takes, 1 to 120; required when `kind` is `next_n`.",
                                            "minimum": 1,
                                            "maximum": 120
                                        }
                                    }
                                },
                                "maxItems": 20
                            }
                        }
                    }
                },
                "title": "UpdatePlanRequest"
            },
            "UpdatePortalDesignRequest": {
                "type": "object",
                "description": "The keys of the portal design to change in the draft. Every key is optional and an omitted one keeps its drafted value; a preset recolours the six colours unless a colour is sent beside it.",
                "properties": {
                    "preset": {
                        "description": "The palette the colours started from: `classic`, `dark`, `midnight`, `paper`, `pastel` or `bold`. Sending it recolours the six colours below from the preset and keeps the colour mode and the grid; send a colour beside it to override that one.",
                        "$ref": "#/components/schemas/PortalPreset"
                    },
                    "color_mode": {
                        "description": "`light` or `dark` paints one palette for everyone; `system` paints the light one and switches to the preset's drawn dark palette when the visitor's browser asks for a dark scheme.",
                        "$ref": "#/components/schemas/PortalColorMode"
                    },
                    "accent": {
                        "type": "string",
                        "description": "The accent, on the buttons, the highlights and the chosen plan's ring, as a six-digit lowercase hex such as `#a3e635`. The text drawn on it is picked by luminance."
                    },
                    "accent_secondary": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The second accent, on the pass-series and pass strips, as a hex colour; `null` paints the preset's own."
                    },
                    "background": {
                        "type": "string",
                        "description": "The page colour behind the cards, as a hex colour."
                    },
                    "grid": {
                        "type": "boolean",
                        "description": "Whether the faint dotted grid is drawn over the page colour."
                    },
                    "surface": {
                        "type": "string",
                        "description": "The cards' colour, as a hex colour."
                    },
                    "text": {
                        "type": "string",
                        "description": "The body text colour, as a hex colour. It must read on the surface and on the background: a pair under a 3:1 contrast ratio is refused."
                    },
                    "heading": {
                        "type": "string",
                        "description": "The colour of the project's name and every heading, as a hex colour, under the same contrast rule as `text`."
                    },
                    "muted": {
                        "type": "string",
                        "description": "The colour of the captions, the labels and the small print, as a hex colour, under the same contrast rule as `text`."
                    },
                    "tagline": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "One line under the project's name, up to 80 characters, or `null` for none."
                    },
                    "social_links": {
                        "type": "array",
                        "description": "Up to 12 links under the card, each `{network, url, label}`: `network` one of {social_networks}; `url` an https address; `label` the name shown for a `custom` link, up to 40 characters, ignored on the others.",
                        "items": {
                            "type": "string"
                        },
                        "minItems": 1
                    },
                    "font_display": {
                        "description": "The face of the headings: `asap-condensed`, `inter`, `poppins`, `montserrat`, `space-grotesk`, `bebas-neue`, `oswald`, `dm-serif-display`, `playfair-display`, `lora`, `manrope` or `sora`.",
                        "$ref": "#/components/schemas/PortalFont"
                    },
                    "font_body": {
                        "description": "The face of everything but the headings, from the same twelve as `font_display`.",
                        "$ref": "#/components/schemas/PortalFont"
                    },
                    "heading_case": {
                        "description": "`uppercase` or `as_written`, for every heading.",
                        "$ref": "#/components/schemas/PortalTextCase"
                    },
                    "type_scale": {
                        "description": "`compact`, `regular` or `large`: one multiplier on every text size.",
                        "$ref": "#/components/schemas/PortalTypeScale"
                    },
                    "radius": {
                        "description": "`sharp`, `soft` or `round` corners on the cards and the fields.",
                        "$ref": "#/components/schemas/PortalRadius"
                    },
                    "button_style": {
                        "description": "`pill`, `rounded` or `square` buttons.",
                        "$ref": "#/components/schemas/PortalButtonStyle"
                    },
                    "button_fill": {
                        "description": "`accent` fills the buttons with the accent, `dark` with the heading colour, `outline` draws them hollow.",
                        "$ref": "#/components/schemas/PortalButtonFill"
                    },
                    "button_case": {
                        "description": "`uppercase` or `as_written`, for every button label.",
                        "$ref": "#/components/schemas/PortalTextCase"
                    },
                    "shadow": {
                        "description": "`none`, `soft` or `strong` shadows under the cards.",
                        "$ref": "#/components/schemas/PortalShadow"
                    },
                    "card_border": {
                        "type": "boolean",
                        "description": "Whether the cards carry a hairline border."
                    },
                    "arrangement": {
                        "description": "`sidebar_left` or `sidebar_right` put the card beside the plans, `stacked` puts it above them, `hero` runs the banner across the top.",
                        "$ref": "#/components/schemas/PortalArrangement"
                    },
                    "content_width": {
                        "description": "`narrow`, `regular` or `wide`: how wide the page runs.",
                        "$ref": "#/components/schemas/PortalWidth"
                    },
                    "sticky_sidebar": {
                        "type": "boolean",
                        "description": "Whether the sidebar card stays in view while the plans scroll."
                    },
                    "plan_grid": {
                        "description": "`list`, `two` or `three`: how many plan cards sit side by side.",
                        "$ref": "#/components/schemas/PortalPlanGrid"
                    },
                    "plan_density": {
                        "description": "`compact` or `roomy` plan cards.",
                        "$ref": "#/components/schemas/PortalDensity"
                    },
                    "plans_heading": {
                        "type": "boolean",
                        "description": "Whether the heading over the plans is shown."
                    },
                    "metrics_subscribers": {
                        "type": "boolean",
                        "description": "Whether the member count is shown on the card."
                    },
                    "metrics_followers": {
                        "type": "boolean",
                        "description": "Whether the follower count is shown on the card."
                    },
                    "metrics_threshold": {
                        "type": "integer",
                        "description": "The count a figure must reach before it is shown, 0 to 1,000,000, so a young project never shows a small number.",
                        "minimum": 0,
                        "maximum": 1000000
                    },
                    "plans_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The heading over the plans, up to 60 characters; `null` for the built-in wording."
                    },
                    "plans_subtitle": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The line under that heading, up to 120 characters; `null` for the built-in wording."
                    },
                    "label_login": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The Login button's label, up to 24 characters; `null` for the built-in wording."
                    },
                    "label_share": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The Share button's label, up to 24 characters; `null` for the built-in wording."
                    },
                    "label_subscribe": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The button on every plan card, up to 24 characters; `null` for the built-in wording."
                    },
                    "checkout_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The checkout's heading, up to 60 characters; `null` for the built-in wording."
                    },
                    "checkout_subtitle": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The line under the checkout's heading, up to 120 characters; `null` for the built-in wording."
                    },
                    "checkout_note": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A note under the checkout, up to 240 characters; `null` for none."
                    },
                    "success_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The heading of the thank-you screen, up to 60 characters; `null` for the built-in wording."
                    },
                    "success_message": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The thank-you screen's message, up to 400 characters; `null` for the built-in wording."
                    },
                    "perks_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The heading over the perks, up to 60 characters; `null` for the built-in one."
                    },
                    "perks": {
                        "type": "array",
                        "description": "Up to 12 perks, each a line of up to 120 characters; the block shows only with at least one.",
                        "items": {
                            "type": "string"
                        },
                        "minItems": 1
                    },
                    "faq_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The heading over the questions, up to 60 characters; `null` for the built-in one."
                    },
                    "faq": {
                        "type": "array",
                        "description": "Up to 12 questions, each `{question, answer}`, the question up to 160 characters and the answer up to 800, both required.",
                        "items": {
                            "type": "string"
                        },
                        "minItems": 1
                    },
                    "about_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The name on the card about the creator, up to 60 characters, or `null`; the card shows when a name or a bio is set."
                    },
                    "about_bio": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The bio on the card about the creator, up to 600 characters, or `null`."
                    },
                    "custom_button_label": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The second button's label, up to 24 characters, sent together with `custom_button_url` or both `null`."
                    },
                    "custom_button_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Where the second button leads, an https or http address up to 255 characters, sent together with `custom_button_label` or both `null`."
                    },
                    "footer_refund_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The refund policy link in the footer, an https or http address, or `null`."
                    },
                    "footer_contact_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The contact link in the footer, an https, http or `mailto:` address, or `null`."
                    },
                    "footer_imprint_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The imprint link in the footer, an https or http address, or `null`."
                    },
                    "footer_line": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A line of small print in the footer, up to 120 characters, or `null`."
                    },
                    "footer_help": {
                        "type": "boolean",
                        "description": "Whether the Help link is shown in the footer."
                    },
                    "announcement_text": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The strip across the top of the page, up to 160 characters, or `null` for no strip."
                    },
                    "announcement_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Where the strip leads, an https or http address, or `null`."
                    },
                    "announcement_starts_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the strip starts showing, ISO 8601 in any zone and stored in UTC, or `null` for at once."
                    },
                    "announcement_ends_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the strip comes down, ISO 8601 and after the start, or `null` for never."
                    },
                    "video_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A YouTube or Vimeo address in any shape the share button gives, stored as the canonical watch address, or `null` for no video."
                    },
                    "gallery_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The heading over the gallery, up to 60 characters; `null` for the built-in one."
                    },
                    "gallery": {
                        "type": "array",
                        "description": "Up to 8 picture addresses, each stored through `POST /v1/projects/{project}/portal-design/images/gallery`.",
                        "items": {
                            "type": "string"
                        },
                        "minItems": 1
                    },
                    "testimonials_title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The heading over the quotes, up to 60 characters; `null` for the built-in one."
                    },
                    "testimonials": {
                        "type": "array",
                        "description": "Up to 12 quotes from members, each `{quote, name, subtitle, avatar_url}`: the words up to 300 characters and the name up to 60, both required; `subtitle` what they are, up to 60 characters, or `null`; `avatar_url` a photo stored through `POST /v1/projects/{project}/portal-design/images/avatar`, or `null` for the first letter of the name.",
                        "items": {
                            "type": "string"
                        },
                        "minItems": 1
                    },
                    "sidebar_items": {
                        "type": "array",
                        "description": "The sidebar card's parts in order, each `{key, shown}` with `key` one of `tagline`, `metrics`, `buttons`, `description`, `social_links`, `footer`, every key exactly once; a part left out is appended, shown.",
                        "items": {
                            "type": "string"
                        },
                        "minItems": 1
                    },
                    "content_blocks": {
                        "type": "array",
                        "description": "The blocks under the plans in order, each `{key, shown}` with `key` one of `perks`, `about`, `faq`, `video`, `gallery`, `testimonials`, every key exactly once; a block left out is appended, shown.",
                        "items": {
                            "type": "string"
                        },
                        "minItems": 1
                    },
                    "locale_switcher": {
                        "type": "boolean",
                        "description": "Whether the list of languages under the card is shown."
                    },
                    "featured_plan_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The plan that carries the Most popular badge, one of the project's own plan ids, or `null` for none."
                    },
                    "coupon_box": {
                        "description": "`always` shows the coupon box on every checkout; `link` shows it only once a coupon arrived with the visit.",
                        "$ref": "#/components/schemas/PortalCouponBox"
                    },
                    "share_button": {
                        "type": "boolean",
                        "description": "Whether the Share button is shown in the header."
                    },
                    "share_networks": {
                        "type": "array",
                        "description": "Which networks the share sheet offers, kept in the sheet's own order: {share_networks}.",
                        "items": {
                            "type": "string"
                        },
                        "minItems": 1
                    },
                    "login_button": {
                        "type": "boolean",
                        "description": "Whether the Login button is shown in the header."
                    },
                    "social_proof": {
                        "type": "boolean",
                        "description": "Whether a line over the plans says how many members joined in the last seven days; it shows only from three up."
                    },
                    "seats_badges": {
                        "type": "boolean",
                        "description": "Whether a pass series card shows how many seats are left."
                    },
                    "seo_indexable": {
                        "type": "boolean",
                        "description": "Whether search engines may list the portal; `false` adds a noindex directive. A portal the project's own readiness keeps out stays unlisted either way."
                    },
                    "seo_social_card": {
                        "type": "boolean",
                        "description": "Whether a shared link unfurls with a card image; `false` leaves the title and the description alone."
                    },
                    "pixel_meta": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The creator's own Meta Pixel id, 10 to 20 digits, or `null`."
                    },
                    "pixel_ga4": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The creator's own Google Analytics 4 measurement id, `G-` followed by 4 to 15 letters or digits, or `null`."
                    },
                    "pixel_tiktok": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The creator's own TikTok Pixel id, 10 to 30 letters or digits, or `null`."
                    },
                    "pixel_google_ads": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The creator's own Google Ads conversion id, `AW-` followed by 6 to 12 digits, or `null`."
                    },
                    "custom_css": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A stylesheet of up to 16,384 characters printed after the theme so its rules win; refused when it would load, run or escape (`@import`, `url(`, `expression(`, `javascript:`, a closing `style` tag and the like); `null` for none."
                    },
                    "seo_title_suffix": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The words after the project's name in the page title, up to 60 characters, or `null` for the built-in ones."
                    },
                    "seo_description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The description search engines and shared links show, up to 160 characters, or `null` for one cut from the project's text."
                    },
                    "social_card_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A card image of the creator's own, stored through `POST /v1/projects/{project}/portal-design/images/card` and sent in the generated card's place, or `null` for the generated card."
                    },
                    "default_locale": {
                        "description": "The language the portal's own address opens in, as a code from `locales`, or `null` for the platform's default.",
                        "anyOf": [
                            {
                                "$ref": "#/components/schemas/Locale"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "locales": {
                        "type": "array",
                        "description": "The languages the switcher offers, as codes from `en`, `fr`, `es`, `it`, `hi`, `bn`, `de`, `pt`, `tr`, `si`, never empty and always carrying `default_locale`.",
                        "items": {
                            "type": "string"
                        },
                        "minItems": 1
                    }
                },
                "title": "UpdatePortalDesignRequest"
            },
            "UpdateProjectRequest": {
                "type": "object",
                "description": "The changes to a project. Every field is optional and an omitted one keeps its value. Send JSON, or `multipart/form-data` when uploading the banner or photo.",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "The project's name, 5 to 255 characters.",
                        "minLength": 5,
                        "maxLength": 255
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the project offers, up to 1,000 characters. HTML is filtered to a safe subset before storage.",
                        "maxLength": 1000
                    },
                    "terms": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uri",
                        "description": "The URL of the terms members are asked to accept, `https://` or `http://`, up to 255 characters.",
                        "maxLength": 255
                    },
                    "privacy": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uri",
                        "description": "The URL of the privacy policy members are asked to accept, `https://` or `http://`, up to 255 characters.",
                        "maxLength": 255
                    },
                    "banner": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "binary",
                        "contentMediaType": "application/octet-stream",
                        "description": "A new banner image (jpg, jpeg, png, gif, bmp, webp or avif), at most 5 MB, as a `multipart/form-data` upload. Processed after the request; read the project again for its URL."
                    },
                    "photo": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "binary",
                        "contentMediaType": "application/octet-stream",
                        "description": "A new photo image (jpg, jpeg, png, gif, bmp, webp or avif), at most 5 MB, as a `multipart/form-data` upload. Processed after the request like the banner."
                    },
                    "storefront_arrangement": {
                        "description": "How the storefronts order the plans on offer: `manual` (the pinned order, always accepted) or `live` (what is on now first, then what opens soonest, then the pinned order). `live` needs the project owner's time-limited passes capability, Growth or the Passes Addon; without it the request is refused with `TEAM_TIER_REQUIRED`.",
                        "$ref": "#/components/schemas/StorefrontArrangement"
                    },
                    "active": {
                        "type": "boolean",
                        "description": "Whether the project is live; the archive and restore endpoints flip the same switch with their own events."
                    },
                    "outage_compensations": {
                        "type": "boolean",
                        "description": "The **Outage Compensation** switch. Set it to false when the creator would rather settle outages themselves, for example with refunds or coupons."
                    },
                    "team_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A team the token's owner belongs to."
                    },
                    "handle": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The portal handle: lowercase letters, digits, dashes and underscores, 5 to 255 characters, unique across every project's current and former handles, on every tier. Changing it moves the portal URL at once; every address the project answered on before keeps redirecting to the current one. Blank switches the portal page off.",
                        "minLength": 5,
                        "maxLength": 255
                    },
                    "hide_branding": {
                        "type": "boolean",
                        "description": "The **Remove Subscriby Branding** switch: true takes the \"Powered by\" mark off the portal page, its social card and the bot, false puts it back. Turning it on needs a tier with the `no_branding` capability (Starter or Growth), `TEAM_TIER_REQUIRED` otherwise; a project whose owner lost the capability keeps the switch and shows the mark until the plan returns."
                    }
                },
                "title": "UpdateProjectRequest"
            },
            "UpdateRecoverySettingsRequest": {
                "type": "object",
                "description": "Which Disaster Recovery settings to change on a project. Every field is optional and an omitted one keeps its value.",
                "properties": {
                    "auto_failover": {
                        "type": "boolean",
                        "description": "Whether the platform may swap a banned channel for its standby on its own. Switching it on needs `accepts_email_fee: true` in the same call and the Growth plan."
                    },
                    "accepts_email_fee": {
                        "type": "boolean",
                        "description": "Consent to the per-email fee a failover may charge for the members the bot cannot reach; consent is not implied by the switch."
                    },
                    "email_delivery": {
                        "description": "How members are told after a channel swap the creator ran: `self` (the creator tells them) or `platform` (Subscriby emails them at the fee).",
                        "$ref": "#/components/schemas/RecoveryEmailDelivery"
                    }
                },
                "title": "UpdateRecoverySettingsRequest"
            },
            "UpdateReferralProgramRequest": {
                "type": "object",
                "description": "The Referral Program settings: what referrers earn, what their friends receive, who may join and which plans count. The first PUT creates the programme; every later PUT changes only the fields it carries.",
                "properties": {
                    "active": {
                        "type": "boolean",
                        "description": "The on/off switch. Prefer the activate and deactivate endpoints, which fire the same event with only that change."
                    },
                    "customers_only": {
                        "type": "boolean",
                        "description": "Whether only members with a live membership may join. Defaults to false."
                    },
                    "approval_required": {
                        "type": "boolean",
                        "description": "Whether you approve each affiliate before their code counts. Defaults to false."
                    },
                    "reward_kind": {
                        "description": "`free_days` (membership days banked on the referrer) or `cash` (a commission you pay out yourself). Defaults to `free_days` on a first save.",
                        "$ref": "#/components/schemas/ReferralRewardKind"
                    },
                    "reward_days": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Days a referrer earns per converted friend, 1 to 3650; required when `reward_kind` is `free_days`.",
                        "minimum": 1,
                        "maximum": 3650
                    },
                    "commission_type": {
                        "description": "`percentage` of every settled payment or a `fixed` amount on the first; required when `reward_kind` is `cash`.",
                        "anyOf": [
                            {
                                "$ref": "#/components/schemas/ReferralCommissionType"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "commission_value": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "The rate: 0.0001 to 100 for a percentage, any amount above zero for a fixed commission. Stored as a decimal string with four places."
                    },
                    "commission_currency_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The currency a `fixed` commission is paid in; required then, cleared for a percentage."
                    },
                    "commission_period_months": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "How long a percentage commission runs after conversion: `0` for the friend's first payment only, 1 to 36 months, or null for life. A fixed commission is always the first payment only.",
                        "minimum": 0,
                        "maximum": 36
                    },
                    "hold_days": {
                        "type": "integer",
                        "description": "Days a cash commission waits before it is payable, so a refund inside the window can take it back: 0 to 90. Defaults to 14.",
                        "minimum": 0,
                        "maximum": 90
                    },
                    "minimum_payout": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "A guide for you, the balance an affiliate reaches before you pay; nothing is enforced. Null for none."
                    },
                    "friend_reward_kind": {
                        "description": "What a referred friend receives on their first purchase: `none`, `free_days` or `coupon`. Defaults to `none`.",
                        "$ref": "#/components/schemas/ReferralFriendRewardKind"
                    },
                    "friend_reward_days": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Days banked on the friend's first purchase, 1 to 3650; required when `friend_reward_kind` is `free_days`.",
                        "minimum": 1,
                        "maximum": 3650
                    },
                    "friend_coupon_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "One of this project's coupon codes, applied at the friend's checkout; required when `friend_reward_kind` is `coupon`. Needs coupon codes on the project owner's plan."
                    },
                    "payout_details_label": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The question affiliates answer so you can pay them, such as `PayPal email`; at most 120 characters. Null for none.",
                        "maxLength": 120
                    },
                    "terms": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Your own terms, shown to affiliates and referred friends; at most 5,000 characters. Null for none.",
                        "maxLength": 5000
                    },
                    "plan_ids": {
                        "type": "array",
                        "description": "Restrict conversions to these plans of the project, at most 200. Omit to leave the restriction alone; send `[]` for every plan, including plans added later.",
                        "items": {
                            "type": "string",
                            "description": "A plan id of this project."
                        },
                        "maxItems": 200
                    }
                },
                "title": "UpdateReferralProgramRequest"
            },
            "UpdateResourceRequest": {
                "type": "object",
                "description": "The changes to a resource. Every field is optional and an omitted one keeps its stored value. `kind` and `space` are not writable: a resource keeps its kind for life, and its place moves only through the connector.",
                "properties": {
                    "title": {
                        "type": "string",
                        "description": "The resource's name on plan cards, 5 to 255 characters.",
                        "minLength": 5,
                        "maxLength": 255
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the resource is, up to 1,000 characters, the same HTML filter as create; null clears it.",
                        "maxLength": 1000
                    },
                    "active": {
                        "type": "boolean",
                        "description": "Whether plans grant it; the activate and deactivate endpoints flip the same switch."
                    }
                },
                "title": "UpdateResourceRequest"
            },
            "UpdateResourceStandbyRequest": {
                "type": "object",
                "description": "The one switch a resource's standby carries.",
                "properties": {
                    "mirror": {
                        "type": "boolean",
                        "description": "Whether every post made in the channel is copied into the standby as it is made. Only a channel can be mirrored, and switching on needs the Growth plan."
                    }
                },
                "required": [
                    "mirror"
                ],
                "title": "UpdateResourceStandbyRequest"
            },
            "UpdateRetentionSettingsRequest": {
                "type": "object",
                "description": "The Revenue Recovery settings of a project: how long a failed renewal keeps access, whether the daily digest is sent, what the cancellation screen asks and which offers it makes, how long a checkout may stay open before it counts as stalled, and how many days before a trial without a card ends its sequence starts. Every field is optional; the row keeps its stored value for each one left out.",
                "properties": {
                    "grace_days": {
                        "type": "integer",
                        "description": "How many days a failed renewal keeps access while the gateway retries, 0 to 30. `0` pauses access at the failure.",
                        "minimum": 0,
                        "maximum": 30
                    },
                    "digest_enabled": {
                        "type": "boolean",
                        "description": "Whether the owner gets one message a day with the failures, reminders, pauses and recoveries, only on a day something happened."
                    },
                    "cancel_feedback_enabled": {
                        "type": "boolean",
                        "description": "Whether the cancellation screen asks the member why before the offer. Off skips straight to the offer."
                    },
                    "offer_pause_enabled": {
                        "type": "boolean",
                        "description": "Whether a cancelling member on Stripe or PayPal is offered one billing cycle on hold. Needs the Growth plan or the Revenue Recovery Addon; ignored by the screen without it."
                    },
                    "offer_discount_coupon_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "One of this project's coupons, applied to the member's renewals where Stripe can carry it, or `null` for no discount offer. Needs the Growth plan or the Revenue Recovery Addon."
                    },
                    "offer_return_coupon_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "One of this project's coupons, handed to the member on the way out on every payment method, or `null` for no return coupon. Needs the Growth plan or the Revenue Recovery Addon."
                    },
                    "checkout_stall_hours": {
                        "type": "integer",
                        "description": "How many hours a checkout may stay open with no settled charge before the hourly sweep counts it as stalled and the stalled-checkout sequences start, 1 to 24; such as `4`.",
                        "minimum": 1,
                        "maximum": 24
                    },
                    "trial_notice_days": {
                        "type": "integer",
                        "description": "How many days before a trial without a card ends its trial-ending sequences start, 1 to 14; such as `3`. A trial shorter than that enrols at its start.",
                        "minimum": 1,
                        "maximum": 14
                    }
                },
                "title": "UpdateRetentionSettingsRequest"
            },
            "UpdateSequenceRequest": {
                "type": "object",
                "description": "The changes to a sequence: any subset of the name, the trigger and the switch, and optionally the whole list of steps in order. Fields left out keep their stored values.",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "A new creator-facing label, 1 to 120 characters.",
                        "minLength": 1,
                        "maxLength": 120
                    },
                    "trigger": {
                        "type": "string",
                        "description": "What enrols a member: `churned`, `lead`, `stalled_checkout` or `trial_ending`. Members already part-way through keep their passage.",
                        "enum": [
                            "churned",
                            "lead",
                            "stalled_checkout",
                            "trial_ending"
                        ]
                    },
                    "active": {
                        "type": "boolean",
                        "description": "Switch the sequence on or off. Off lets every member part-way through go, as `sequence.exited` with the reason `disabled`, and enrols nobody until it runs again."
                    },
                    "steps": {
                        "type": "array",
                        "description": "The whole list of steps in order, at most 8; it replaces the stored list. A step still at its place keeps its id and a member due it keeps their position. Omit to leave the steps alone; send `[]` to remove them all.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "delay_days": {
                                    "type": "integer",
                                    "description": "Days after the trigger for the first step, 0 to 180 (`0` goes out on the next hourly run); days after the step before for the rest, 1 to 180.",
                                    "minimum": 0,
                                    "maximum": 180
                                },
                                "body": {
                                    "type": "string",
                                    "description": "The message in the creator's words, 1 to 1,000 characters, with `{name}`, `{project}`, `{coupon}`, `{discount}` and `{link}` filled per member at send time."
                                },
                                "coupon_id": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "One of this project's coupons to carry with the step, or `null`."
                                }
                            },
                            "required": [
                                "delay_days",
                                "body"
                            ]
                        },
                        "maxItems": 8
                    }
                },
                "title": "UpdateSequenceRequest"
            },
            "UpdateSmartLinkRequest": {
                "type": "object",
                "description": "The changes to a Smart Link: any subset of the create shape. The code, and with it the bot link and the cookie, never change; renaming the slug moves the web address only.",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "A new label, 2 to 120 characters.",
                        "minLength": 2,
                        "maxLength": 120
                    },
                    "slug": {
                        "type": "string",
                        "description": "A new address segment, 2 to 32 letters, digits and hyphens, lowercased before the uniqueness check against the project's other links; the old address stops answering.",
                        "pattern": "^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$",
                        "minLength": 2,
                        "maxLength": 32
                    },
                    "destination": {
                        "description": "`portal`, `plan` (needs `plan_id`, sent or already stored) or `bot`.",
                        "$ref": "#/components/schemas/SmartLinkDestination"
                    },
                    "plan_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The plan a `plan` destination opens; one of this project's plans. Ignored when the destination is not, or stops being, a plan."
                    },
                    "expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the link stops counting, ISO 8601 and in the future, or null to run until archived."
                    }
                },
                "title": "UpdateSmartLinkRequest"
            },
            "UpdateSupportCannedReplyRequest": {
                "type": "object",
                "description": "The changes to a saved reply. Every field is optional and an omitted one keeps its stored value, so a snippet can be renamed without resending its body.",
                "properties": {
                    "title": {
                        "type": "string",
                        "description": "The label shown in the picker, 2 to 80 characters.",
                        "minLength": 2,
                        "maxLength": 80
                    },
                    "body": {
                        "type": "string",
                        "description": "The text sent to the member, 2 to 4,000 characters. Replies already sent with the old wording are untouched: a saved reply is copied into a message when it is used, not referenced.",
                        "minLength": 2,
                        "maxLength": 4000
                    },
                    "shortcut": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Up to 30 letters, numbers, dashes and underscores, unique within the project. Send null to clear it. The uniqueness check ignores the snippet being edited, so resending its own shortcut is fine.",
                        "pattern": "^[A-Za-z0-9_-]+$",
                        "maxLength": 30
                    },
                    "sort_order": {
                        "type": "integer",
                        "description": "The position in the picker, 0 to 999.",
                        "minimum": 0,
                        "maximum": 999
                    }
                },
                "title": "UpdateSupportCannedReplyRequest"
            },
            "UpdateSupportSettingsRequest": {
                "type": "object",
                "description": "The changes to a project's support inbox settings. Every field is optional and an omitted one keeps its stored value.",
                "properties": {
                    "enabled": {
                        "type": "boolean",
                        "description": "Whether a member's unrecognised message to the bot opens a conversation."
                    },
                    "relay_mode": {
                        "type": "string",
                        "description": "`owner_dm`, `forum_group` or `none`. Switching to `forum_group` does not link a group: the creator adds the project bot to a group with topics enabled as an administrator, the bot records the group itself and confirms; until then new member messages reach only the dashboard inbox.",
                        "enum": [
                            "owner_dm",
                            "forum_group",
                            "none"
                        ]
                    },
                    "agent_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The name outbound replies are prefixed with, up to 60 characters; null or an empty string clears it. Whitespace is trimmed.",
                        "maxLength": 60
                    },
                    "auto_reply": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The acknowledgement sent on a member's first message in a thread, up to 1,000 characters, well under the platform limit because it is sent with an identity header; null clears it.",
                        "maxLength": 1000
                    },
                    "notify_email": {
                        "type": "boolean",
                        "description": "Whether the creator is emailed about new support activity."
                    },
                    "copilot_answers": {
                        "type": "boolean",
                        "description": "Whether Subscriby Copilot answers members' own-subscription questions and what the project's Knowledge covers in the inbox and the project bot, marked as automated; everything else still waits for a person."
                    },
                    "copilot_portal": {
                        "type": "boolean",
                        "description": "Whether a signed-in member finds the same Copilot in a chat on the project's portal page."
                    }
                },
                "title": "UpdateSupportSettingsRequest"
            },
            "UpdateTeamMemberRoleRequest": {
                "type": "object",
                "description": "The role to move a collaborator onto.",
                "properties": {
                    "role": {
                        "type": "string",
                        "description": "A role **code** on the team, such as `manager`, not a role id. An unknown code is refused.",
                        "maxLength": 255
                    }
                },
                "required": [
                    "role"
                ],
                "title": "UpdateTeamMemberRoleRequest"
            },
            "UploadPortalDesignImageRequest": {
                "type": "object",
                "description": "The picture to store, as multipart form data.",
                "properties": {
                    "image": {
                        "type": "string",
                        "format": "binary",
                        "contentMediaType": "application/octet-stream",
                        "description": "A JPG, PNG, GIF or WEBP picture of at most 5 MB; it is cut to the slot's size from the centre."
                    }
                },
                "required": [
                    "image"
                ],
                "title": "UploadPortalDesignImageRequest"
            },
            "UserIdentityResource": {
                "type": "object",
                "description": "A linked identity: an account the creator holds on a connector, tied to their Subscriby account. Secrets and chat rows are never returned.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The link's id, the value the unlink endpoint takes.",
                        "examples": [
                            "0c2d8a7e-4b1f-4d3e-9a6b-2f5e8c1d7a90"
                        ]
                    },
                    "connector": {
                        "type": "string",
                        "description": "The connector the account is on, by key.",
                        "examples": [
                            "telegram"
                        ]
                    },
                    "purpose": {
                        "type": "string",
                        "description": "`primary` for the account that signs the creator in and receives alerts; `backup` for the account registered for Disaster Recovery.",
                        "enum": [
                            "primary",
                            "backup"
                        ],
                        "examples": [
                            "primary"
                        ]
                    },
                    "source": {
                        "type": "string",
                        "description": "How the link was proven: `handshake` (completed from Settings), `bot` (the account came in through the connector's own flow), `backfill` (migrated from before connectors), `portal` or `adopted`.",
                        "enum": [
                            "bot",
                            "portal",
                            "handshake",
                            "adopted",
                            "backfill"
                        ],
                        "examples": [
                            "handshake"
                        ]
                    },
                    "external_id": {
                        "type": "string",
                        "description": "The platform's own id for the account, so an integration can match the creator against the connector's records.",
                        "examples": [
                            "123456789"
                        ]
                    },
                    "display_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the platform calls the person.",
                        "examples": [
                            "Ada Lovelace"
                        ]
                    },
                    "username": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The account's handle when the platform has one; null otherwise.",
                        "examples": [
                            "ada"
                        ]
                    },
                    "linked_at": {
                        "type": "string",
                        "description": "When the account was linked, ISO 8601.",
                        "examples": [
                            "2026-09-12T10:05:00Z"
                        ]
                    },
                    "verified_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the link was proven, ISO 8601; null while unverified.",
                        "examples": [
                            "2026-09-12T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "connector",
                    "purpose",
                    "source",
                    "external_id",
                    "display_name",
                    "username",
                    "linked_at",
                    "verified_at"
                ],
                "title": "UserIdentityResource"
            },
            "WebhookDeliveryFilter": {
                "type": "string",
                "description": "The status tab on the webhook delivery log. One case per delivery status plus \"all\", so the tab is an enum-backed Livewire property instead of a free string compared against a list in the query.\n",
                "enum": [
                    "all",
                    "pending",
                    "delivered",
                    "failed",
                    "dead"
                ],
                "title": "WebhookDeliveryFilter"
            },
            "WebhookDeliveryResource": {
                "type": "object",
                "description": "One row of the webhook delivery log: one endpoint, one event, the signed envelope that was posted, what the target answered and where the row is on the retry ladder.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The delivery's id, the value the retry endpoint takes.",
                        "examples": [
                            "34f1d78e-05a2-4b69-8c3d-7e921ab06f45"
                        ]
                    },
                    "endpoint_id": {
                        "type": "string",
                        "description": "The webhook endpoint the event was posted to.",
                        "examples": [
                            "c62a08f4-1b7d-4e35-9860-a37f5d21e0b9"
                        ]
                    },
                    "event": {
                        "type": "string",
                        "description": "The event name, as the catalog lists it.",
                        "examples": [
                            "subscription.created"
                        ]
                    },
                    "event_id": {
                        "type": "string",
                        "description": "The 26-character ULID the envelope's `id` carries without its `evt_` prefix; also the `SB-Event-Id` header the handler received.",
                        "examples": [
                            "01HXZ3Q8M7Y2K4N6P9R1T3V5W7"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "`pending` (born, or reset by a retry), `failed` (a non-2xx or transport error while retries remain), `delivered` (the first 2xx) or `dead` (the ladder ran out or the endpoint vanished). `delivered` and `dead` are final until a retry.",
                        "enum": [
                            "pending",
                            "delivered",
                            "failed",
                            "dead"
                        ],
                        "examples": [
                            "failed"
                        ]
                    },
                    "attempts": {
                        "type": "integer",
                        "description": "Posts made so far. Reset to 0 by a retry.",
                        "examples": [
                            2
                        ]
                    },
                    "response_status": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The HTTP status the endpoint returned on the last attempt; null before the first post or after a transport failure.",
                        "examples": [
                            500
                        ]
                    },
                    "response_excerpt": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The start of the response body, or the transport error; null before the first post.",
                        "examples": [
                            "upstream unavailable"
                        ]
                    },
                    "payload": {
                        "type": "array",
                        "description": "The full event envelope that was, or would have been, posted, so a consumer can be debugged against it exactly.",
                        "items": {}
                    },
                    "next_attempt_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the worker will post a `failed` row again, ISO 8601; null otherwise.",
                        "examples": [
                            "2026-09-06T10:15:00+00:00"
                        ]
                    },
                    "delivered_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Stamped on the first 2xx, ISO 8601; null until then.",
                        "examples": [
                            null
                        ]
                    },
                    "dead_lettered_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Stamped when the ladder ran out, ISO 8601; null otherwise.",
                        "examples": [
                            null
                        ]
                    },
                    "created_at": {
                        "type": "string",
                        "description": "When the row was born, ISO 8601.",
                        "examples": [
                            "2026-09-06T10:05:00+00:00"
                        ]
                    }
                },
                "required": [
                    "id",
                    "endpoint_id",
                    "event",
                    "event_id",
                    "status",
                    "attempts",
                    "response_status",
                    "response_excerpt",
                    "payload",
                    "next_attempt_at",
                    "delivered_at",
                    "dead_lettered_at",
                    "created_at"
                ],
                "title": "WebhookDeliveryResource"
            },
            "WebhookEndpointResource": {
                "type": "object",
                "description": "A webhook endpoint: a target Subscriby posts events to, with its subscriptions and delivery health. The signing secret never appears here.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The endpoint's id.",
                        "examples": [
                            "c62a08f4-1b7d-4e35-9860-a37f5d21e0b9"
                        ]
                    },
                    "name": {
                        "type": "string",
                        "description": "The label the endpoint was registered with, 3 to 100 characters.",
                        "examples": [
                            "Zapier trigger"
                        ]
                    },
                    "url": {
                        "type": "string",
                        "description": "The `https://` URL events are posted to.",
                        "examples": [
                            "https://hooks.zapier.com/hooks/catch/..."
                        ]
                    },
                    "project_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The project the endpoint is confined to; null for a team-wide endpoint that receives every project's events.",
                        "examples": [
                            null
                        ]
                    },
                    "events": {
                        "type": "array",
                        "description": "The event names the endpoint is subscribed to.",
                        "items": {
                            "description": "An event name from the webhook event catalog, such as `subscription.created`.",
                            "examples": [
                                "subscription.created"
                            ]
                        }
                    },
                    "is_active": {
                        "type": "boolean",
                        "description": "Whether deliveries flow. False while paused by the creator or switched off by the worker after too many consecutive failures.",
                        "examples": [
                            true
                        ]
                    },
                    "disabled_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the endpoint was paused or auto-disabled, ISO 8601; null while active.",
                        "examples": [
                            null
                        ]
                    },
                    "allowed_ips": {
                        "type": [
                            "array",
                            "null"
                        ],
                        "description": "IPv4/IPv6 addresses or CIDR ranges the target must resolve to; a delivery whose host resolves elsewhere is dead-lettered without being posted. Null when unrestricted.",
                        "examples": [
                            null
                        ],
                        "items": {
                            "description": "An address or CIDR range, such as `198.51.100.7` or `2001:db8::/32`."
                        }
                    },
                    "failure_count": {
                        "type": "integer",
                        "description": "How many deliveries have failed over the endpoint's lifetime.",
                        "examples": [
                            0
                        ]
                    },
                    "consecutive_failures": {
                        "type": "integer",
                        "description": "The current failure streak; the worker disables the endpoint when it reaches the limit, and resuming resets it.",
                        "examples": [
                            0
                        ]
                    },
                    "last_success_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a delivery last got a 2xx, ISO 8601; null until one has.",
                        "examples": [
                            null
                        ]
                    },
                    "last_failure_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a delivery last failed, ISO 8601; null until one has.",
                        "examples": [
                            null
                        ]
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the endpoint was registered, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the endpoint last changed, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    }
                },
                "required": [
                    "id",
                    "name",
                    "url",
                    "project_id",
                    "events",
                    "is_active",
                    "disabled_at",
                    "allowed_ips",
                    "failure_count",
                    "consecutive_failures",
                    "last_success_at",
                    "last_failure_at",
                    "created_at",
                    "updated_at"
                ],
                "title": "WebhookEndpointResource"
            },
            "WebhookEventResource": {
                "type": "object",
                "description": "A stored delivery rendered as the envelope the live webhook POST carried, so a polled sample is indistinguishable from a live payload.",
                "properties": {
                    "id": {
                        "description": "The event id, `evt_` followed by a 26-character ULID; the same value the `SB-Event-Id` header carries without the prefix.",
                        "examples": [
                            "evt_01HXZ3Q8M7Y2K4N6P9R1T3V5W7"
                        ]
                    },
                    "type": {
                        "description": "The event name, such as `subscription.created`.",
                        "examples": [
                            "subscription.created"
                        ]
                    },
                    "created_at": {
                        "description": "When the event was raised, ISO 8601.",
                        "examples": [
                            "2026-05-18T10:05:00Z"
                        ]
                    },
                    "api_version": {
                        "description": "The payload-envelope version the dispatcher stamped at delivery time, `2026-05-01` today.",
                        "examples": [
                            "2026-05-01"
                        ]
                    },
                    "project_id": {
                        "description": "The project the event concerns; null for account-level events.",
                        "examples": [
                            "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13"
                        ]
                    },
                    "data": {
                        "description": "The event's payload, exactly as the event's reference page documents it."
                    }
                },
                "required": [
                    "id",
                    "type",
                    "created_at",
                    "api_version",
                    "project_id",
                    "data"
                ],
                "title": "WebhookEventResource"
            }
        },
        "responses": {
            "Unauthenticated": {
                "description": "`AUTHENTICATION_REQUIRED`: the request carries no bearer token, or one that is revoked, malformed, or minted for another environment (an `sbt_test_` token on production).",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ApiError"
                        },
                        "examples": {
                            "AUTHENTICATION_REQUIRED": {
                                "summary": "AUTHENTICATION_REQUIRED",
                                "value": {
                                    "error": {
                                        "code": "AUTHENTICATION_REQUIRED",
                                        "message": "A valid API token is required for this endpoint.",
                                        "docs_url": "https://docs.subscriby.net/api/v1/errors#authentication-required",
                                        "remediation": "Send the request with an Authorization: Bearer <sbt_...> header using a token minted at /settings/tokens.",
                                        "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "Forbidden": {
                "description": "`TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ApiError"
                        },
                        "examples": {
                            "TOKEN_MISSING_ABILITY": {
                                "summary": "TOKEN_MISSING_ABILITY",
                                "value": {
                                    "error": {
                                        "code": "TOKEN_MISSING_ABILITY",
                                        "message": "The presented API token does not carry the ability required to perform this action.",
                                        "docs_url": "https://docs.subscriby.net/api/v1/errors#token-missing-ability",
                                        "remediation": "Mint a new token including the ability listed in error.required_ability, or ask the team owner to grant it.",
                                        "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                        "context": {
                                            "required_ability": "project:view"
                                        }
                                    }
                                }
                            },
                            "FORBIDDEN": {
                                "summary": "FORBIDDEN",
                                "value": {
                                    "error": {
                                        "code": "FORBIDDEN",
                                        "message": "The token holder can see this resource but may not change it.",
                                        "docs_url": "https://docs.subscriby.net/api/v1/errors#forbidden",
                                        "remediation": "Only the member who registered the resource, or the team owner, may change it. Ask one of them, or mint the token as that member.",
                                        "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                    }
                                }
                            },
                            "TEAM_TIER_REQUIRED": {
                                "summary": "TEAM_TIER_REQUIRED",
                                "value": {
                                    "error": {
                                        "code": "TEAM_TIER_REQUIRED",
                                        "message": "This operation requires the creator's account to be on the Growth plan.",
                                        "docs_url": "https://docs.subscriby.net/api/v1/errors#team-tier-required",
                                        "remediation": "Upgrade the creator to the Growth plan from /settings/billing.",
                                        "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                    }
                                }
                            },
                            "CONNECTOR_TIER_REQUIRED": {
                                "summary": "CONNECTOR_TIER_REQUIRED",
                                "value": {
                                    "error": {
                                        "code": "CONNECTOR_TIER_REQUIRED",
                                        "message": "The connector needs a higher plan on the creator's account: a second connector on the same project needs the Growth plan, and a connector reserved for a paid tier needs that tier or higher.",
                                        "docs_url": "https://docs.subscriby.net/api/v1/errors#connector-tier-required",
                                        "remediation": "Upgrade the creator to the Growth plan from /settings/billing, or uninstall the project's other connector first.",
                                        "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "ValidationFailed": {
                "description": "`VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ApiError"
                        },
                        "examples": {
                            "VALIDATION_FAILED": {
                                "summary": "VALIDATION_FAILED",
                                "value": {
                                    "error": {
                                        "code": "VALIDATION_FAILED",
                                        "message": "The request payload failed validation.",
                                        "docs_url": "https://docs.subscriby.net/api/v1/errors#validation-failed",
                                        "remediation": "Inspect the error.fields map to discover which keys failed validation and why.",
                                        "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10",
                                        "fields": {
                                            "name": [
                                                "The name field is required."
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "RateLimited": {
                "description": "`RATE_LIMITED`: the token has spent its 300 requests a minute or 10,000 an hour; `Retry-After` says when the next one is accepted.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ApiError"
                        },
                        "examples": {
                            "RATE_LIMITED": {
                                "summary": "RATE_LIMITED",
                                "value": {
                                    "error": {
                                        "code": "RATE_LIMITED",
                                        "message": "The rate limit for this token has been exceeded.",
                                        "docs_url": "https://docs.subscriby.net/api/v1/errors#rate-limited",
                                        "remediation": "Back off and retry after the time hinted by the Retry-After header.",
                                        "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "NotFound": {
                "description": "`RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ApiError"
                        },
                        "examples": {
                            "RESOURCE_NOT_FOUND": {
                                "summary": "RESOURCE_NOT_FOUND",
                                "value": {
                                    "error": {
                                        "code": "RESOURCE_NOT_FOUND",
                                        "message": "The requested resource could not be found.",
                                        "docs_url": "https://docs.subscriby.net/api/v1/errors#resource-not-found",
                                        "remediation": "Double-check the UUID in the path. The resource may have been deleted or never existed.",
                                        "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                    }
                                }
                            },
                            "TENANT_MISMATCH": {
                                "summary": "TENANT_MISMATCH",
                                "value": {
                                    "error": {
                                        "code": "TENANT_MISMATCH",
                                        "message": "The requested resource does not belong to the team this API token is scoped to.",
                                        "docs_url": "https://docs.subscriby.net/api/v1/errors#tenant-mismatch",
                                        "remediation": "Use a token minted for the correct team, or switch the creator's current team before minting.",
                                        "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "IdempotencyKeyMissing": {
                "description": "`IDEMPOTENCY_KEY_MISSING`: every write needs an `Idempotency-Key` header. Send a fresh UUID per distinct operation.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ApiError"
                        },
                        "examples": {
                            "IDEMPOTENCY_KEY_MISSING": {
                                "summary": "IDEMPOTENCY_KEY_MISSING",
                                "value": {
                                    "error": {
                                        "code": "IDEMPOTENCY_KEY_MISSING",
                                        "message": "An Idempotency-Key header is required on this endpoint.",
                                        "docs_url": "https://docs.subscriby.net/api/v1/errors#idempotency-key-missing",
                                        "remediation": "Re-send the request with Idempotency-Key: <uuid>; every mutation endpoint requires one.",
                                        "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "IdempotencyKeyReused": {
                "description": "`IDEMPOTENCY_KEY_REUSED`: the key was already used in the last 24 hours with a different request body.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ApiError"
                        },
                        "examples": {
                            "IDEMPOTENCY_KEY_REUSED": {
                                "summary": "IDEMPOTENCY_KEY_REUSED",
                                "value": {
                                    "error": {
                                        "code": "IDEMPOTENCY_KEY_REUSED",
                                        "message": "The supplied Idempotency-Key was already used with a different request body.",
                                        "docs_url": "https://docs.subscriby.net/api/v1/errors#idempotency-key-reused",
                                        "remediation": "Choose a fresh Idempotency-Key per distinct operation. The server caches responses for 24h per key.",
                                        "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "IdempotencyReplayInProgress": {
                "description": "`IDEMPOTENCY_REPLAY_IN_PROGRESS`: the first request with this key is still running; retry in a few seconds and the original response is replayed.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ApiError"
                        },
                        "examples": {
                            "IDEMPOTENCY_REPLAY_IN_PROGRESS": {
                                "summary": "IDEMPOTENCY_REPLAY_IN_PROGRESS",
                                "value": {
                                    "error": {
                                        "code": "IDEMPOTENCY_REPLAY_IN_PROGRESS",
                                        "message": "A prior request with the same Idempotency-Key is still in flight.",
                                        "docs_url": "https://docs.subscriby.net/api/v1/errors#idempotency-replay-in-progress",
                                        "remediation": "Wait a few seconds and retry; the original request has not yet finished.",
                                        "request_id": "0199a4b1-2f6e-7d3a-8c41-9e7b5d2a6f10"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}