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. |
Contact.Created
Section titled “Contact.Created”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
Section titled “Contact.Updated”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
Section titled “Contact.Deleted”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.