Webhook event reference

Webhooks notify your website/app of events that happen in Memberful, such as when a member creates an account, a subscription is updated, or a plan is deleted.

This article lists all the events that can trigger a webhook. If you're looking for an explanation of how to set up and use webhooks, check out our main article about Webhooks.

In this help doc:

Member events

Member accounts are created automatically when a member purchases a subscription or registers for free (if that feature is enabled). You can also create member accounts manually from your dashboard.

Most webhook types follow the object.event naming convention. Member events currently follow an object_event convention instead. Pay close attention to the event names laid out in this doc.

member_signup

Sent when a new member account is created.

Use this webhook to add new members to your app or to a third-party service.

 {
  "event": "member_signup",
  "member": {
    "address": {
      "street": "Street",
      "city": "City",
      "state": "State",
      "postal_code": "Postal code",
      "country": "City"
    },
    "created_at": 1749075331,
    "credit_card": {
      "exp_month": 1,
      "exp_year": 2040
    },
    "custom_field": "Custom field value",
    "discord_user_id": "000000000000000000",
    "email": "john.doe@example.com",
    "first_name": "John",
    "full_name": "John Doe",
    "id": 0,
    "last_name": "Doe",
    "phone_number": "555-12345",
    "signup_method": "checkout",
    "stripe_customer_id": "cus_00000",
    "tracking_params": {
      "utm_term": "shoes",
      "utm_campaign": "summer_sale",
      "utm_medium": "social",
      "utm_source": "instagram",
      "utm_content": "textlink"
    },
    "unrestricted_access": false,
    "username": "john_doe"
  }
}

member_updated

Sent when a member's profile information is updated.

Use this webhook to update a member's profile information in your app.

This will not be triggered when a member updates their answers to custom fields. Use the custom_fields.updated webhook to detect custom field updates.

 {
  "event": "member_updated",
  "member": {
    "address": {
      "street": "Street",
      "city": "City",
      "state": "State",
      "postal_code": "Postal code",
      "country": "City"
    },
    "created_at": 1749075331,
    "credit_card": {
      "exp_month": 1,
      "exp_year": 2040
    },
    "custom_field": "Custom field value",
    "discord_user_id": "000000000000000000",
    "email": "john.doe@example.com",
    "first_name": "John",
    "full_name": "John Doe",
    "id": 0,
    "last_name": "Doe",
    "phone_number": "555-12345",
    "signup_method": "checkout",
    "stripe_customer_id": "cus_00000",
    "tracking_params": {
      "utm_term": "shoes",
      "utm_campaign": "summer_sale",
      "utm_medium": "social",
      "utm_source": "instagram",
      "utm_content": "textlink"
    },
    "unrestricted_access": false,
    "username": "john_doe"
  },
  "changed": {
    "email": [
      "old_email@example.com",
      "john.doe@example.com"
    ]
  }
}

member.deleted

Sent when a member is deleted from your Memberful account.

Use this webhook to remove a member from your app if they were deleted from Memberful.

It's not common for a member account to be deleted — in most cases, you'll want to react to Subscription Deactivated instead.

 {
  "event": "member.deleted",
  "member": {
    "deleted": true,
    "id": 0
  }
}

tax_id.updated

Sent when a member adds, changes, or removes their tax ID.

Use this trigger to update your app when a member updates their tax ID.

 {
  "event": "tax_id.updated",
  "member": {
    "address": {
      "street": "Street",
      "city": "City",
      "state": "State",
      "postal_code": "Postal code",
      "country": "City"
    },
    "created_at": 1749075331,
    "credit_card": {
      "exp_month": 1,
      "exp_year": 2040
    },
    "custom_field": "Custom field value",
    "discord_user_id": "000000000000000000",
    "email": "john.doe@example.com",
    "first_name": "John",
    "full_name": "John Doe",
    "id": 0,
    "last_name": "Doe",
    "phone_number": "555-12345",
    "signup_method": "checkout",
    "stripe_customer_id": "cus_00000",
    "tracking_params": {
      "utm_term": "shoes",
      "utm_campaign": "summer_sale",
      "utm_medium": "social",
      "utm_source": "instagram",
      "utm_content": "textlink"
    },
    "unrestricted_access": false,
    "username": "john_doe"
  },
  "tax_id": {
    "country": "FR",
    "type": "eu_vat",
    "value": "FR1234567890"
  }
}

custom_fields.updated

Sent when a member answers or updates their custom fields. The value field can be a String, an Array of Strings, or an empty Array.

Use this trigger to update your app when a member updates their answers to custom fields, either during checkout or by visiting their member profile.

 {
  "event": "custom_fields.updated",
  "member": {
    "address": {
      "street": "Street",
      "city": "City",
      "state": "State",
      "postal_code": "Postal code",
      "country": "City"
    },
    "created_at": 1749075331,
    "credit_card": {
      "exp_month": 1,
      "exp_year": 2040
    },
    "discord_user_id": "000000000000000000",
    "email": "john.doe@example.com",
    "first_name": "John",
    "full_name": "John Doe",
    "id": 0,
    "last_name": "Doe",
    "phone_number": "555-12345",
    "signup_method": "checkout",
    "stripe_customer_id": "cus_00000",
    "tracking_params": {
      "utm_term": "shoes",
      "utm_campaign": "summer_sale",
      "utm_medium": "social",
      "utm_source": "instagram",
      "utm_content": "textlink"
    },
    "unrestricted_access": false,
    "username": "john_doe"
  },
  "custom_fields": [
    {
      "field": {
        "id": 1,
        "label": "Who's your favorite writer?"
      },
      "value": "John Doe"
    },
    {
      "field": {
        "id": 2,
        "label": "What's your t-shirt size?"
      },
      "value": ""
    },
    {
      "field": {
        "id": 3,
        "label": "How do you consume our content?"
      },
      "value": [
        "Podcast",
        "Newsletter"
      ]
    }
  ]
}

Subscription events

Sent when a member subscribes to a plan or when that subscription is updated, renewed, or deleted.

Almost all times across all webhooks are returned as Unix time, but subscription events use ISO 8601 for the following attributes: `activated_at`, `created_at`, `expires_at`, `trial_end_at`, and `trial_start_at`.

subscription.created

Sent when a new subscription is added to a member's account. This includes when a member purchases a subscription or activates a gifted subscription, when a member is added to a group subscription, and when a staff account manually creates a subscription.

Use this webhook to let your app know when a member has subscribed.

 {
  "event": "subscription.created",
  "subscription": {
    "active": true,
    "autorenew": true,
    "created_at": "2025-06-04T22:15:31Z",
    "expires_at": "2025-07-04T22:15:31Z",
    "id": 1,
    "member": {
      "address": {
        "street": "Street",
        "city": "City",
        "state": "State",
        "postal_code": "Postal code",
        "country": "City"
      },
      "created_at": 1749075331,
      "credit_card": {
        "exp_month": 1,
        "exp_year": 2040
      },
      "custom_field": "Custom field value",
      "discord_user_id": "000000000000000000",
      "email": "john.doe@example.com",
      "first_name": "John",
      "full_name": "John Doe",
      "id": 0,
      "last_name": "Doe",
      "phone_number": "555-12345",
      "signup_method": "checkout",
      "stripe_customer_id": "cus_00000",
      "tracking_params": {
        "utm_term": "shoes",
        "utm_campaign": "summer_sale",
        "utm_medium": "social",
        "utm_source": "instagram",
        "utm_content": "textlink"
      },
      "unrestricted_access": false,
      "username": "john_doe"
    },
    "subscription_plan": {
      "id": 0,
      "interval_count": 1,
      "interval_unit": "month",
      "name": "Sample plan",
      "price_cents": 100000000,
      "slug": "0-sample-plan"
    },
    "trial_end_at": null,
    "trial_start_at": null
  }
}

subscription.updated

Sent when a member's subscription is updated.

If you want to know if the update is a plan change, you'll need to see if the plan_id field is present in the changed object. The first value is the old plan and the second value is the new one. The same applies to other changed fields.

 {
  "event": "subscription.updated",
  "subscription": {
    "active": true,
    "autorenew": true,
    "created_at": "2025-06-04T22:15:31Z",
    "expires_at": "2025-07-04T22:15:31Z",
    "id": 1,
    "member": {
      "address": {
        "street": "Street",
        "city": "City",
        "state": "State",
        "postal_code": "Postal code",
        "country": "City"
      },
      "created_at": 1749075331,
      "credit_card": {
        "exp_month": 1,
        "exp_year": 2040
      },
      "custom_field": "Custom field value",
      "discord_user_id": "000000000000000000",
      "email": "john.doe@example.com",
      "first_name": "John",
      "full_name": "John Doe",
      "id": 0,
      "last_name": "Doe",
      "phone_number": "555-12345",
      "signup_method": "checkout",
      "stripe_customer_id": "cus_00000",
      "tracking_params": {
        "utm_term": "shoes",
        "utm_campaign": "summer_sale",
        "utm_medium": "social",
        "utm_source": "instagram",
        "utm_content": "textlink"
      },
      "unrestricted_access": false,
      "username": "john_doe"
    },
    "subscription_plan": {
      "id": 0,
      "interval_count": 1,
      "interval_unit": "month",
      "name": "Sample plan",
      "price_cents": 100000000,
      "slug": "0-sample-plan"
    },
    "trial_end_at": null,
    "trial_start_at": null
  },
  "changed": {
    "plan_id": [
      42,
      0
    ],
    "expires_at": [
      "2025-07-04T22:15:31Z",
      "2025-08-03T22:15:31Z"
    ],
    "autorenew": [
      false,
      true
    ]
  }
}

subscription.renewed

Sent when a member's subscription is renewed or when a returning member reactivates an old subscription.

Use this webhook to renew the member's access to your app. At this time there's no way to differentiate between a renewal and a reactivation, but you could reach out to our API to find out more about the subscription's history.

 {
  "event": "subscription.renewed",
  "subscription": {
    "active": true,
    "autorenew": true,
    "created_at": "2025-06-04T22:15:31Z",
    "expires_at": "2025-07-04T22:15:31Z",
    "id": 1,
    "member": {
      "address": {
        "street": "Street",
        "city": "City",
        "state": "State",
        "postal_code": "Postal code",
        "country": "City"
      },
      "created_at": 1749075331,
      "credit_card": {
        "exp_month": 1,
        "exp_year": 2040
      },
      "custom_field": "Custom field value",
      "discord_user_id": "000000000000000000",
      "email": "john.doe@example.com",
      "first_name": "John",
      "full_name": "John Doe",
      "id": 0,
      "last_name": "Doe",
      "phone_number": "555-12345",
      "signup_method": "checkout",
      "stripe_customer_id": "cus_00000",
      "tracking_params": {
        "utm_term": "shoes",
        "utm_campaign": "summer_sale",
        "utm_medium": "social",
        "utm_source": "instagram",
        "utm_content": "textlink"
      },
      "unrestricted_access": false,
      "username": "john_doe"
    },
    "subscription_plan": {
      "id": 0,
      "interval_count": 1,
      "interval_unit": "month",
      "name": "Sample plan",
      "price_cents": 100000000,
      "slug": "0-sample-plan"
    },
    "trial_end_at": null,
    "trial_start_at": null
  },
  "order": {
    "created_at": "2025-06-04T22:15:31Z",
    "status": "completed",
    "total": 9900,
    "uuid": "4DACB7B0-B728-0130-F9E8-102B343DC979"
  }
}

subscription.activated

Sent when a suspended order is marked completed by staff and the subscription becomes active again.

Sent when a member's (suspended order)[/help/manage-your-members/pause-a-subscription/#suspend-the-order] is marked by staff as complete and the subscription becomes active again.

This does not refer to when a member reactivates a previously expired subscription — use the Subscription Renewed trigger for that.

 {
  "event": "subscription.activated",
  "subscription": {
    "active": true,
    "autorenew": true,
    "created_at": "2025-06-04T22:15:31Z",
    "expires_at": "2025-07-04T22:15:31Z",
    "id": 1,
    "member": {
      "address": {
        "street": "Street",
        "city": "City",
        "state": "State",
        "postal_code": "Postal code",
        "country": "City"
      },
      "created_at": 1749075331,
      "credit_card": {
        "exp_month": 1,
        "exp_year": 2040
      },
      "custom_field": "Custom field value",
      "discord_user_id": "000000000000000000",
      "email": "john.doe@example.com",
      "first_name": "John",
      "full_name": "John Doe",
      "id": 0,
      "last_name": "Doe",
      "phone_number": "555-12345",
      "signup_method": "checkout",
      "stripe_customer_id": "cus_00000",
      "tracking_params": {
        "utm_term": "shoes",
        "utm_campaign": "summer_sale",
        "utm_medium": "social",
        "utm_source": "instagram",
        "utm_content": "textlink"
      },
      "unrestricted_access": false,
      "username": "john_doe"
    },
    "subscription_plan": {
      "id": 0,
      "interval_count": 1,
      "interval_unit": "month",
      "name": "Sample plan",
      "price_cents": 100000000,
      "slug": "0-sample-plan"
    },
    "trial_end_at": null,
    "trial_start_at": null
  }
}

subscription.deactivated

Sent when a member's subscription fails to renew, expires, or becomes inactive.

Sent when a member's subscription fails to renew, expires, or becomes inactive. Also sent when a staff account suspends an order, making the subscription inactive.

Use this webhook to remove the member's access to your app or to update their status if they stop paying.

 {
  "event": "subscription.deactivated",
  "subscription": {
    "active": false,
    "autorenew": true,
    "created_at": "2025-06-04T22:15:31Z",
    "expires_at": "2025-07-04T22:15:31Z",
    "id": 1,
    "member": {
      "address": {
        "street": "Street",
        "city": "City",
        "state": "State",
        "postal_code": "Postal code",
        "country": "City"
      },
      "created_at": 1749075331,
      "credit_card": {
        "exp_month": 1,
        "exp_year": 2040
      },
      "custom_field": "Custom field value",
      "discord_user_id": "000000000000000000",
      "email": "john.doe@example.com",
      "first_name": "John",
      "full_name": "John Doe",
      "id": 0,
      "last_name": "Doe",
      "phone_number": "555-12345",
      "signup_method": "checkout",
      "stripe_customer_id": "cus_00000",
      "tracking_params": {
        "utm_term": "shoes",
        "utm_campaign": "summer_sale",
        "utm_medium": "social",
        "utm_source": "instagram",
        "utm_content": "textlink"
      },
      "unrestricted_access": false,
      "username": "john_doe"
    },
    "subscription_plan": {
      "id": 0,
      "interval_count": 1,
      "interval_unit": "month",
      "name": "Sample plan",
      "price_cents": 100000000,
      "slug": "0-sample-plan"
    },
    "trial_end_at": null,
    "trial_start_at": null
  }
}

subscription.deleted

Sent when a staff account deletes a member’s subscription from the Memberful dashboard.

Use this webhook to remove the member's access to your app or to update their status.

 {
  "event": "subscription.deleted",
  "subscription": {
    "active": true,
    "autorenew": true,
    "created_at": "2025-06-04T22:15:31Z",
    "expires_at": "2025-07-04T22:15:31Z",
    "id": 1,
    "member": {
      "address": {
        "street": "Street",
        "city": "City",
        "state": "State",
        "postal_code": "Postal code",
        "country": "City"
      },
      "created_at": 1749075331,
      "credit_card": {
        "exp_month": 1,
        "exp_year": 2040
      },
      "custom_field": "Custom field value",
      "discord_user_id": "000000000000000000",
      "email": "john.doe@example.com",
      "first_name": "John",
      "full_name": "John Doe",
      "id": 0,
      "last_name": "Doe",
      "phone_number": "555-12345",
      "signup_method": "checkout",
      "stripe_customer_id": "cus_00000",
      "tracking_params": {
        "utm_term": "shoes",
        "utm_campaign": "summer_sale",
        "utm_medium": "social",
        "utm_source": "instagram",
        "utm_content": "textlink"
      },
      "unrestricted_access": false,
      "username": "john_doe"
    },
    "subscription_plan": {
      "id": 0,
      "interval_count": 1,
      "interval_unit": "month",
      "name": "Sample plan",
      "price_cents": 100000000,
      "slug": "0-sample-plan"
    },
    "trial_end_at": null,
    "trial_start_at": null
  }
}

Order events

Sent when a member places an order to purchase plans or downloads.

Custom fields are now collected after checkout, which means they're no longer set when the order_purchased event is triggered. To access them, webhook recipients must now use the custom_fields.updated event instead.

order.purchased

Sent when a member places an order or when a staff account manually adds an order to a member's account.

This is not triggered for renewal payments.

A member purchasing a gift subscription for someone else will trigger this webhook, but no subscription will be created until the recipient activates their gift.

Use this webhook to notify your app when a member makes a purchase.

 {
  "event": "order.purchased",
  "order": {
    "uuid": "4DACB7B0-B728-0130-F9E8-102B343DC979",
    "number": "4DACB7B0",
    "total": 9900,
    "status": "completed",
    "receipt": "receipt text",
    "member": {
      "address": {
        "street": "Street",
        "city": "City",
        "state": "State",
        "postal_code": "Postal code",
        "country": "City"
      },
      "created_at": 1749075331,
      "credit_card": {
        "exp_month": 1,
        "exp_year": 2040
      },
      "custom_field": "Custom field value",
      "discord_user_id": "000000000000000000",
      "email": "john.doe@example.com",
      "first_name": "John",
      "full_name": "John Doe",
      "id": 0,
      "last_name": "Doe",
      "phone_number": "555-12345",
      "signup_method": "checkout",
      "stripe_customer_id": "cus_00000",
      "tracking_params": {
        "utm_term": "shoes",
        "utm_campaign": "summer_sale",
        "utm_medium": "social",
        "utm_source": "instagram",
        "utm_content": "textlink"
      },
      "unrestricted_access": false,
      "username": "john_doe"
    },
    "products": [

    ],
    "subscriptions": [
      {
        "active": true,
        "created_at": 1749075331,
        "expires": true,
        "expires_at": 1751667331,
        "id": 0,
        "in_trial_period": false,
        "subscription": {
          "id": 0,
          "price": 1000,
          "name": "Sample plan",
          "slug": "0-sample-plan",
          "renewal_period": "monthly",
          "interval_unit": "month",
          "interval_count": 1,
          "for_sale": true
        },
        "trial_end_at": null,
        "trial_start_at": null
      }
    ]
  }
}

order.refunded

Sent when a staff account refunds an order.

Use this trigger to update your app when a refund has been processed.

 {
  "event": "order.refunded",
  "order": {
    "uuid": "4DACB7B0-B728-0130-F9E8-102B343DC979",
    "number": "4DACB7B0",
    "total": 9900,
    "status": "refunded",
    "receipt": "receipt text",
    "member": {
      "address": {
        "street": "Street",
        "city": "City",
        "state": "State",
        "postal_code": "Postal code",
        "country": "City"
      },
      "created_at": 1749075331,
      "credit_card": {
        "exp_month": 1,
        "exp_year": 2040
      },
      "custom_field": "Custom field value",
      "discord_user_id": "000000000000000000",
      "email": "john.doe@example.com",
      "first_name": "John",
      "full_name": "John Doe",
      "id": 0,
      "last_name": "Doe",
      "phone_number": "555-12345",
      "signup_method": "checkout",
      "stripe_customer_id": "cus_00000",
      "tracking_params": {
        "utm_term": "shoes",
        "utm_campaign": "summer_sale",
        "utm_medium": "social",
        "utm_source": "instagram",
        "utm_content": "textlink"
      },
      "unrestricted_access": false,
      "username": "john_doe"
    },
    "products": [

    ],
    "subscriptions": [
      {
        "active": true,
        "created_at": 1749075331,
        "expires": true,
        "expires_at": 1751667331,
        "id": 0,
        "in_trial_period": false,
        "subscription": {
          "id": 0,
          "price": 1000,
          "name": "Sample plan",
          "slug": "0-sample-plan",
          "renewal_period": "monthly",
          "interval_unit": "month",
          "interval_count": 1,
          "for_sale": true
        },
        "trial_end_at": null,
        "trial_start_at": null
      }
    ]
  }
}

order.suspended

Sent when an order is suspended by staff.

 {
  "event": "order.suspended",
  "order": {
    "uuid": "4DACB7B0-B728-0130-F9E8-102B343DC979",
    "number": "4DACB7B0",
    "total": 9900,
    "status": "suspended",
    "receipt": "receipt text",
    "member": {
      "address": {
        "street": "Street",
        "city": "City",
        "state": "State",
        "postal_code": "Postal code",
        "country": "City"
      },
      "created_at": 1749075331,
      "credit_card": {
        "exp_month": 1,
        "exp_year": 2040
      },
      "custom_field": "Custom field value",
      "discord_user_id": "000000000000000000",
      "email": "john.doe@example.com",
      "first_name": "John",
      "full_name": "John Doe",
      "id": 0,
      "last_name": "Doe",
      "phone_number": "555-12345",
      "signup_method": "checkout",
      "stripe_customer_id": "cus_00000",
      "tracking_params": {
        "utm_term": "shoes",
        "utm_campaign": "summer_sale",
        "utm_medium": "social",
        "utm_source": "instagram",
        "utm_content": "textlink"
      },
      "unrestricted_access": false,
      "username": "john_doe"
    },
    "products": [

    ],
    "subscriptions": [
      {
        "active": true,
        "created_at": 1749075331,
        "expires": true,
        "expires_at": 1751667331,
        "id": 0,
        "in_trial_period": false,
        "subscription": {
          "id": 0,
          "price": 1000,
          "name": "Sample plan",
          "slug": "0-sample-plan",
          "renewal_period": "monthly",
          "interval_unit": "month",
          "interval_count": 1,
          "for_sale": true
        },
        "trial_end_at": null,
        "trial_start_at": null
      }
    ]
  }
}

order.completed

Sent when a suspended order is marked completed by staff.

 {
  "event": "order.completed",
  "order": {
    "uuid": "4DACB7B0-B728-0130-F9E8-102B343DC979",
    "number": "4DACB7B0",
    "total": 9900,
    "status": "completed",
    "receipt": "receipt text",
    "member": {
      "address": {
        "street": "Street",
        "city": "City",
        "state": "State",
        "postal_code": "Postal code",
        "country": "City"
      },
      "created_at": 1749075331,
      "credit_card": {
        "exp_month": 1,
        "exp_year": 2040
      },
      "custom_field": "Custom field value",
      "discord_user_id": "000000000000000000",
      "email": "john.doe@example.com",
      "first_name": "John",
      "full_name": "John Doe",
      "id": 0,
      "last_name": "Doe",
      "phone_number": "555-12345",
      "signup_method": "checkout",
      "stripe_customer_id": "cus_00000",
      "tracking_params": {
        "utm_term": "shoes",
        "utm_campaign": "summer_sale",
        "utm_medium": "social",
        "utm_source": "instagram",
        "utm_content": "textlink"
      },
      "unrestricted_access": false,
      "username": "john_doe"
    },
    "products": [

    ],
    "subscriptions": [
      {
        "active": true,
        "created_at": 1749075331,
        "expires": true,
        "expires_at": 1751667331,
        "id": 0,
        "in_trial_period": false,
        "subscription": {
          "id": 0,
          "price": 1000,
          "name": "Sample plan",
          "slug": "0-sample-plan",
          "renewal_period": "monthly",
          "interval_unit": "month",
          "interval_count": 1,
          "for_sale": true
        },
        "trial_end_at": null,
        "trial_start_at": null
      }
    ]
  }
}

Plan events

Sent when staff accounts create, update, or delete plans.

subscription_plan.created

Sent when a new plan is created.

 {
  "event": "subscription_plan.created",
  "subscription": {
    "id": 0,
    "price": 1000,
    "name": "Sample plan",
    "slug": "0-sample-plan",
    "renewal_period": "monthly",
    "interval_unit": "month",
    "interval_count": 1,
    "for_sale": true
  }
}

subscription_plan.updated

Sent when a plan is updated.

 {
  "event": "subscription_plan.updated",
  "subscription": {
    "id": 0,
    "price": 1000,
    "name": "Sample plan",
    "slug": "0-sample-plan",
    "renewal_period": "monthly",
    "interval_unit": "month",
    "interval_count": 1,
    "for_sale": true
  }
}

subscription_plan.deleted

Sent when a plan is deleted.

 {
  "event": "subscription_plan.deleted",
  "subscription": {
    "id": 0,
    "price": 1000,
    "name": "Sample plan",
    "slug": "0-sample-plan",
    "renewal_period": "monthly",
    "interval_unit": "month",
    "interval_count": 1,
    "for_sale": true
  }
}

Download events

Staff can create downloads to include with plans or to sell separately.

download.created

Sent when a download is created.

 {
  "event": "download.created",
  "product": {
    "id": 0,
    "name": "Sample download",
    "price": 1000,
    "slug": "0-sample-download",
    "for_sale": true
  }
}

download.updated

Sent when a download is updated.

 {
  "event": "download.updated",
  "product": {
    "id": 0,
    "name": "Sample download",
    "price": 1000,
    "slug": "0-sample-download",
    "for_sale": true
  }
}

download.deleted

Sent when a download is deleted.

 {
  "event": "download.deleted",
  "product": {
    "id": 0,
    "name": "Sample download",
    "price": 1000,
    "slug": "0-sample-download",
    "for_sale": true
  }
}

How upgrades/downgrades are handled

Both upgrades and downgrades trigger the subscription.updated webhook.

Upgrades include a "changed" section detailing the changes:

"changed": {
    "plan_id": [
      42,
      0
    ],
    "expires_at": [
      "2023-05-12T15:09:58Z",
      "2023-06-11T15:09:58Z"
    ],
    "autorenew": [
      false,
      true
    ]
  }

Downgrades tend to happen on the next renewal date (since the member already paid a higher price for their current period, they're not downgraded immediately). In that case, the "Changed" section will be empty.

Related help docs:

Can't find what you're looking for? We'd love to help! 💪

Send us a message and you'll hear back within a few hours Monday - Friday. 😀