diff --git a/x-api/activity/event-payloads.mdx b/x-api/activity/event-payloads.mdx index 3c8c7c496..a7522b08c 100644 --- a/x-api/activity/event-payloads.mdx +++ b/x-api/activity/event-payloads.mdx @@ -1229,6 +1229,129 @@ Fired when the filtered user unfollows another user, or is unfollowed. Same `sou ``` --- +## Subscription events + +Subscription events use a `source` / `target` user pair similar to follow events. Private events — require user-context authentication with the `follows.read` scope. + +### `subscriptions.subscribe` + +Fired when the filtered user subscribes to another user, or is subscribed to by another user, using the paid subscriptions button on the profile page. The `payload` includes `source` (the subscriber) and `target` (the user being subscribed to). + +```json title="subscriptions.subscribe" expandable lines wrap icon="/icons/xds/icon-brackets.svg" +{ + "data": { + "event_uuid": "1093427633808192000", + "filter": { + "user_id": "123456789" + }, + "event_type": "subscriptions.subscribe", + "payload": { + "source": { + "data": { + "id": "123456789", + "username": "subscriber_user", + "name": "Subscriber User", + "created_at": "2024-08-31T23:23:51.000Z", + "description": "Example subscriber", + "profile_image_url": "https://pbs.twimg.com/profile_images/123456789/example_normal.jpg", + "protected": false, + "verified": false, + "public_metrics": { + "followers_count": 100, + "following_count": 50, + "tweet_count": 250, + "listed_count": 2, + "like_count": 500, + "media_count": 25 + } + } + }, + "target": { + "data": { + "id": "987654321", + "username": "creator_user", + "name": "Creator User", + "created_at": "2020-01-15T12:00:00.000Z", + "description": "Example creator", + "profile_image_url": "https://pbs.twimg.com/profile_images/987654321/example_normal.jpg", + "protected": false, + "verified": true, + "verified_type": "blue", + "public_metrics": { + "followers_count": 10000, + "following_count": 200, + "tweet_count": 5000, + "listed_count": 150, + "like_count": 3000, + "media_count": 400 + } + } + } + } + } +} +``` + +### `subscriptions.unsubscribe` + +Fired when the filtered user unsubscribes to another user, or is unsubscribed from. Emitted when the subscription actually expires, not upon cancellation, since the subscription is still active until expiration. Same `source` / `target` shape as `subscriptions.subscribe`. + +```json title="subscriptions.unsubscribe" expandable lines wrap icon="/icons/xds/icon-brackets.svg" +{ + "data": { + "event_uuid": "1093427633808192001", + "filter": { + "user_id": "123456789" + }, + "event_type": "subscriptions.unsubscribe", + "payload": { + "source": { + "data": { + "id": "123456789", + "username": "subscriber_user", + "name": "Subscriber User", + "created_at": "2024-08-31T23:23:51.000Z", + "description": "Example subscriber", + "profile_image_url": "https://pbs.twimg.com/profile_images/123456789/example_normal.jpg", + "protected": false, + "verified": false, + "public_metrics": { + "followers_count": 100, + "following_count": 50, + "tweet_count": 250, + "listed_count": 2, + "like_count": 500, + "media_count": 25 + } + } + }, + "target": { + "data": { + "id": "987654321", + "username": "creator_user", + "name": "Creator User", + "created_at": "2020-01-15T12:00:00.000Z", + "description": "Example creator", + "profile_image_url": "https://pbs.twimg.com/profile_images/987654321/example_normal.jpg", + "protected": false, + "verified": true, + "verified_type": "blue", + "public_metrics": { + "followers_count": 10000, + "following_count": 200, + "tweet_count": 5000, + "listed_count": 150, + "like_count": 3000, + "media_count": 400 + } + } + } + } + } +} +``` +--- + ## Profile events All `profile.update.*` events share a `before` / `after` payload shape. diff --git a/x-api/activity/introduction.mdx b/x-api/activity/introduction.mdx index 25d130119..26e3434bf 100644 --- a/x-api/activity/introduction.mdx +++ b/x-api/activity/introduction.mdx @@ -69,13 +69,26 @@ Like events are triggered when a user likes a Post, or when one of the user's ow ### Follow events -Follow events are triggered when the filtered user follows another user, or is followed by another user. +Follow events are triggered when the filtered user follows another user, or is followed by another user. Supports the `direction` qualifier. | Event Name | Description | Filters | | --- | --- | --- | | `follow.follow` | Fired when a user follows another user | `user_id` | | `follow.unfollow` | Fired when a user unfollows another user | `user_id` | +### Subscription events + +Subscription events are triggered when the filtered user subscribes to another user, or is subscribed to by another user, using the paid subscriptions button on the profile page. Supports the `direction` qualifier. + +| Event Name | Description | Filters | +| --- | --- | --- | +| `subscriptions.subscribe` | Fired when a user subscribes to another user | `user_id` | +| `subscriptions.unsubscribe` | Fired when a user unsubscribes to another user. Emitted when the subscription actually expires, not upon cancellation, since the subscription is still active until expiration | `user_id` | + + + **Private events:** Subscription events are private and require user-context (OAuth 2.0) authentication with the `follows.read` scope. See [Event privacy and authentication](#event-privacy-and-authentication) below. + + ### Profile events Profile events are triggered when a user makes changes to their profile information. @@ -193,7 +206,7 @@ The following qualifiers are currently supported: | Qualifier | Values | Supported events | | --- | --- | --- | | `conversation_type` | `direct`, `group` | `chat.received` | -| `direction` | `inbound`, `outbound` | `follow.follow`, `follow.unfollow`, `like.create` | +| `direction` | `inbound`, `outbound` | `follow.follow`, `follow.unfollow`, `like.create`, `subscriptions.subscribe`, `subscriptions.unsubscribe` | The `direction` qualifier is equivalent to the top-level `filter.direction` field. Both remain supported. @@ -248,6 +261,7 @@ Private events are activities that require explicit user consent through OAuth a - Post replies (`post.reply.create`) — requires the `tweet.read` scope - Post quotes (`post.quote.create`) — requires the `tweet.read` scope - Post reposts (`post.repost.create`) — requires the `tweet.read` scope +- Subscriptions (`subscriptions.subscribe`, `subscriptions.unsubscribe`) — requires the `follows.read` scope - Mutes (`mute.mute`, `mute.unmute`) — requires the `mute.read` scope - Blocks (`block.block`, `block.unblock`) — requires the `block.read` scope - Broadcast chats (`broadcast.chat`) — requires the `broadcast.read` scope