Skip to content

Contact events

Contact events describe a non-demo user’s Contact relationship with the club that owns the webhook subscription. Each uses a Contacts/{userId} subject and includes ClubId and UserId in data. These events do not expose private notes, health data, or Athlete-only activity.

Event type When it is sent Typical action
Contact.Created A user becomes a Contact, including when an Athlete is removed and remains a Contact. Upsert the club-scoped Contact.
Contact.Updated The user’s profile or the club-specific ClientStage is updated; the visible snapshot may be unchanged. Refresh or upsert the Contact snapshot.
Contact.Deleted The Contact is removed, converted to an Athlete, or the global user is deleted. Remove the Contact relationship; handle conversion separately.

data uses the same ClubContactDTO shape as GET /Contacts/{userId}. This representative event is abbreviated:

[
{
"id": "example-contact-created-event",
"topic": "club-100001-events",
"subject": "Contacts/300001",
"data": {
"ClubId": 100001,
"UserId": 300001,
"Email": "contact@example.test",
"FirstMidName": "Alex",
"LastName": "Example",
"CreatedAt": "2026-09-15T10:30:00+00:00",
"JoinedAt": null,
"ClientStage": "Lead"
},
"eventType": "Contact.Created",
"eventTime": "2026-09-15T10:30:00Z",
"dataVersion": "1.0"
}
]

Use data.UserId as the public identifier and data.ClubId as the club scope. Do not parse either value from subject or topic.

Contact.Updated contains a full Contact snapshot, not a JSON patch. Its data shape is the same as Contact.Created. Upsert the snapshot, or call GET /Contacts/{userId} when you need current state. Do not assume that delivery order matches change order. An update can be delivered even when no field in the Contact representation changed.

The dedicated PUT /Contacts/{userId}/ClientStage operation sends this existing event type after a real stage change. Repeating the same stage does not send another state-change event. No new event type or payload shape is needed for a commercial-stage update.

Contact.Deleted contains the last available Contact snapshot plus Reason:

[
{
"id": "example-contact-deleted-event",
"topic": "club-100001-events",
"subject": "Contacts/300001",
"data": {
"ClubId": 100001,
"UserId": 300001,
"Email": "contact@example.test",
"CreatedAt": "2026-09-15T10:30:00+00:00",
"Reason": "ConvertedToAthlete"
},
"eventType": "Contact.Deleted",
"eventTime": "2026-09-15T11:00:00Z",
"dataVersion": "1.0"
}
]
Reason Meaning
Removed The Contact relationship with this club was explicitly removed.
ConvertedToAthlete The user became an Athlete of this club; look for Athlete.Created or read the Athlete by the same UserId.
UserDeleted The global Uptivo user was deleted.

Reason describes why this Contact relationship ended. It is not a command to delete the corresponding person from your own CRM. A following GET /Contacts/{userId} can return 404; process the deletion from its snapshot, and make it idempotent. During conversion, keep the Contact and Athlete views separate and avoid letting an older Contact event recreate a stale relationship.

See the event catalog for the common envelope, deduplication, and compatibility rules.