Skip to content

UserSubscription events

UserSubscription events describe a Subscription product assigned to an athlete. All three event types use a UserSubscriptions/{userSubscriptionId} subject and the same data contract.

Event type Meaning
UserSubscription.Created A Subscription was assigned to an athlete.
UserSubscription.Updated Validity, activity balance, billing, or suspension data changed.
UserSubscription.Deleted The assignment was deleted.

The public names UserSubscription and UserClassSubscriptionId refer to the same assignment resource. See Subscriptions for the catalog and User subscriptions for the assignment lifecycle.

[
{
"id": "example-user-subscription-created-event",
"topic": "club-100001-events",
"subject": "UserSubscriptions/600001",
"data": {
"UserClassSubscriptionId": 600001,
"ClassSubscriptionId": 500001,
"UserId": 300001,
"From": "2026-09-01T00:00:00+00:00",
"To": "2026-10-01T00:00:00+00:00",
"DurationDays": 30,
"MaxActivities": 8,
"AvailableActivities": 8,
"ClassSubscriptionPlanId": 510001,
"SuspendedAtUTC": null,
"SuspensionStartUTC": null,
"ReactivationDate": null,
"SuspensionState": "None",
"IsSuspended": false,
"SuspendedDays": 0,
"Disabled": false
},
"eventType": "UserSubscription.Created",
"eventTime": "2026-09-07T14:12:43Z",
"dataVersion": "1.0"
}
]

Use data.UserClassSubscriptionId as the assignment identifier, data.ClassSubscriptionId as the catalog product identifier, and data.UserId as the athlete identifier.

This example shows an active suspension. Use SuspensionStartUTC as the start instant and tolerate SuspendedAtUTC as a compatibility alias.

[
{
"id": "example-user-subscription-updated-event",
"topic": "club-100001-events",
"subject": "UserSubscriptions/600001",
"data": {
"UserClassSubscriptionId": 600001,
"ClassSubscriptionId": 500001,
"UserId": 300001,
"From": "2026-08-11T00:00:00+00:00",
"To": "2026-09-15T00:00:00+00:00",
"DurationDays": 30,
"MaxActivities": 8,
"AvailableActivities": 5,
"SuspendedAtUTC": "2026-09-10T00:00:00Z",
"SuspensionStartUTC": "2026-09-10T00:00:00Z",
"ReactivationDate": "2026-09-15T00:00:00+00:00",
"SuspensionState": "Active",
"IsSuspended": true,
"SuspendedDays": 5,
"Disabled": false
},
"eventType": "UserSubscription.Updated",
"eventTime": "2026-09-10T08:00:00Z",
"dataVersion": "1.0"
}
]

SuspensionState can be None, Scheduled, or Active. IsSuspended is false for a scheduled future suspension and becomes true only while the suspension is active. These values describe the state when the payload was serialized; call GET /UserSubscriptions/{userSubscriptionId} when decisions depend on the current instant.

The deletion event carries the last assignment snapshot and uses the same schema:

[
{
"id": "example-user-subscription-deleted-event",
"topic": "club-100001-events",
"subject": "UserSubscriptions/600001",
"data": {
"UserClassSubscriptionId": 600001,
"ClassSubscriptionId": 500001,
"UserId": 300001,
"From": "2026-09-01T00:00:00+00:00",
"To": "2026-10-01T00:00:00+00:00",
"MaxActivities": 8,
"AvailableActivities": 5
},
"eventType": "UserSubscription.Deleted",
"eventTime": "2026-09-12T14:22:57Z",
"dataVersion": "1.0"
}
]

Treat the payload as a tombstone: the corresponding GET normally returns 404. Remove or archive the local assignment idempotently without deleting the athlete or the catalog Subscription.

  1. Deduplicate by envelope id.
  2. Upsert Created and Updated using UserClassSubscriptionId.
  3. Re-evaluate eligibility when validity, balance, Disabled, or suspension fields change.
  4. Remove only the athlete assignment for Deleted.
  5. Fetch the resource when current time-dependent suspension state matters.