> ## Documentation Index
> Fetch the complete documentation index at: https://api.fanvue.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# App Subscription Events

> app.subscription.activated and app.subscription.cancel_at_period_end_changed for your app's own subscriptions.

Two events share the `subscription` resource. They are delivered in the
[Standard-Webhooks envelope](/docs/app-store/webhooks#event-envelope); the fields
below describe the `data` object. Every event requires the `read:self` scope.

| Event (`type`)                                  | Fires when                                                  |
| ----------------------------------------------- | ----------------------------------------------------------- |
| `app.subscription.activated`                    | A subscription becomes active                               |
| `app.subscription.cancel_at_period_end_changed` | Auto-renew is turned off; access continues until period end |

Fanvue models cancellation as `cancel_at_period_end` plus an `expires_at`, not an
immediate removal: a buyer who cancels keeps access until `expires_at`. Gate
access on `expires_at`, not on `status`.

The money and the access state are separate events: a subscription's initial
charge emits **both**
[`app.payment.succeeded`](/docs/app-store/webhooks/payments) (with
`billing_reason: subscription_initial`) **and** `app.subscription.activated`.

<Note>
  `app.subscription.deactivated` is reserved for when a subscription's access
  actually ends, but is **not emitted yet**. Read live subscription state with
  the [App Subscriptions](/docs/app-store/app-subscriptions) endpoints in the
  meantime.
</Note>

## Subscription resource

`data.object` is `"subscription"` for both events.

| Field                      | Type           | Description                                                      |
| -------------------------- | -------------- | ---------------------------------------------------------------- |
| `object`                   | string         | Always `"subscription"`                                          |
| `id`                       | string         | Subscription id                                                  |
| `status`                   | string         | `active` \| `cancelled` \| `expired`                             |
| `cancel_at_period_end`     | boolean        | Whether the subscription will stop renewing at `expires_at`      |
| `expires_at`               | string \| null | ISO 8601 end of the current period                               |
| `created_at`               | string \| null | ISO 8601 time the subscription started                           |
| `plan`                     | object         | `{ uuid }` of the subscribed pricing plan (`uuid` may be `null`) |
| `provider_subscription_id` | string \| null | Upstream provider subscription id, if any                        |
| `app`                      | object         | `{ uuid }` of your app                                           |
| `buyer`                    | object         | `{ uuid }` of the buyer                                          |
| `metadata`                 | object         | Reserved passthrough metadata map (currently always empty)       |

## Examples

### `app.subscription.activated`

```json theme={null}
{
  "id": "3d4e5f60718293a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f708",
  "type": "app.subscription.activated",
  "timestamp": "2026-06-17T13:12:45.200Z",
  "data": {
    "object": "subscription",
    "id": "3f9a2b71-1c4e-4f8a-9d2b-7c6e5a4b3d21",
    "status": "active",
    "cancel_at_period_end": false,
    "expires_at": "2026-07-17T13:12:45.000Z",
    "created_at": "2026-06-17T13:12:45.000Z",
    "plan": { "uuid": "b2d7c9f0-4a13-4e6b-8f25-1a9c3e7d5b80" },
    "provider_subscription_id": "psub_8a0f2d4b6c8e",
    "app": { "uuid": "a1c3e5f7-9b2d-4c6e-8a0f-2d4b6c8e0a13" },
    "buyer": { "uuid": "c4e6a8b0-2d4f-6a81-0c2e-4b6d8f0a2c46" },
    "metadata": {}
  }
}
```

### `app.subscription.cancel_at_period_end_changed`

```json theme={null}
{
  "id": "4e5f60718293a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f70819",
  "type": "app.subscription.cancel_at_period_end_changed",
  "timestamp": "2026-06-20T09:00:00.000Z",
  "data": {
    "object": "subscription",
    "id": "3f9a2b71-1c4e-4f8a-9d2b-7c6e5a4b3d21",
    "status": "cancelled",
    "cancel_at_period_end": true,
    "expires_at": "2026-07-17T13:12:45.000Z",
    "created_at": "2026-06-17T13:12:45.000Z",
    "plan": { "uuid": "b2d7c9f0-4a13-4e6b-8f25-1a9c3e7d5b80" },
    "provider_subscription_id": "psub_8a0f2d4b6c8e",
    "app": { "uuid": "a1c3e5f7-9b2d-4c6e-8a0f-2d4b6c8e0a13" },
    "buyer": { "uuid": "c4e6a8b0-2d4f-6a81-0c2e-4b6d8f0a2c46" },
    "metadata": {}
  }
}
```

## Reconciling

Because `app.subscription.deactivated` is not emitted yet, and because webhooks
can be missed or delayed, read live subscription state from the [App
Subscriptions](/docs/app-store/app-subscriptions) endpoints rather than deriving it
from events alone.
