Webhooks are a way to receive data from Vital. We frequently poll to receive data from the various providers. By registering webhooks, you avoid unnecessarily hitting our servers for data. We have several webhook event types that you can subscribe to. You can see these in the dashboard under the webhooks sections.

Historical Data Flow

When a user first connects a device to Vital, Vital backend pulls historical data. Historical data is all data that exists on a user’s account, prior to them linking their wearable account with Vital. This can take several minutes for all the data to be retrieved and to be readily accessible.

When data is available, the backend triggers a historical.data.<resource_type>.created webhook event. The resource_type is determined by the provider - more information on which resources a provider can support can be found here.

We send a webhook event for each resource a provider supports. In certain cases, where a user has large amounts of historical data, we send webhook events for each ordered-chunk (most-recent first). The is_final flag is used to indicate that the data collection is complete.

Webhook Event
{
  "event_type": "historical.data.workouts.created",
  "data": {
    "user_id": "e9e072e8-...",
    "start_date": "2020-06-21T08:23:01+00:00",
    "end_date": "1996-11-02T14:39:28+00:00",
    "is_final": true,
    "provider": "zwift"
  }
}

When you receive the historical backfill event, you should make an API call for the specific resource you received the webhook event for. As an example, if you receive the event historical.data.workouts.created you should make a call to GET workout data from the API. Historical data can be quite big, so we don’t send the full payload in a webhook.

Daily Data Flow

After a user has connected and historical data is backfilled, any new data is sent in the payload of the daily.data.<resource_type>.* webhook.

Examples of each payload are provided in the webhooks dashboard. You can send test events which contain the different payloads you may receive throughout the integrations lifecyle.

The event structure and deduplication semantic of summary types and timeseries types have a few key differences. Please refer to Event Structure for a more in-depth discussion.
Webhook Event
{
  "event_type": "daily.data.workouts.created",
  "data": {
    "id": "c90bd6fb-...",
    "average_hr": 198,
    "distance": 8544,
    "time_start": "2012-11-24T22:57:01+00:00",
    "time_end": "2017-04-22T04:57:31+00:00",
    "calories": 4470,
    "hr_zones": [8279],
    "user_id": "ab3247dc-...",
    "moving_time": 4719,
    "total_elevation_gain": 8967,
    "elev_high": 3868,
    "max_speed": 8371,
    "average_watts": 9029,
    "max_watts": 1551,
    "provider_id": "dolor ipsum reiciendis Lorem veniam elit. esse",
    "source": {
      "name": "Zwift",
      "slug": "zwift",
      "logo": "https://logo.png"
    }
  }
}

Connection Created

Once a connection between a provider and a user is established, we will send a webhook confirming it.

Webhook Event
{
  "event_type": "provider.connection.created",
  "data": {
    "user_id": "4eca10f9-...",
    "source": {
      "source_name": "Strava",
      "source_slug": "strava",
      "source_logo": "https://storage.googleapis.com/vital-assets/strava.png"
    }
  }
}

Deep Dive into Vital Webhooks