Notifications
You may subscribe your users to get notifications for certain classes of errors or new items to be sent directly to your site via WebHook or collected periodically.
For webhooks, the basic workflow for this is that you would provide us with a URL to be notified and potentially a filter. You can choose to be notified with each item or as a generic notification. Your site must use SSL using a non-self-served certificate. You should not whitelist our IP addresses as we updated our addresses regularly for scalability reasons. Each message sent to you is signed with your OAuth2 Secret Key, as described in Verifying Webhook Requests.

For pull notifications, you optionally provide us with a filter, and then periodically collect the notifications, acquire the data, and delete any claims.

Once notifications are enabled for your account, then you can subscribe a user using the API below. When the user adds a new item, this item would be sent or made available to your notification system.
If your account has multiple notification rules, you only need to subscribe once per user.
The request to your server will be a POST request containing:
| POST Parameter Name | Description |
|---|---|
| context | A JSON Object containing at a minimum the notificationKey from below. |
| file | For non-generic pushes, this would contain the GPX/TCX/FIT/PWX/KML/KMZ/etc. file. |
| sourceId | For non-generic pushes, this would be the id of the SourceData that generated this item. |
| itemId | For non-generic objects, this would be the item id. |
Your server must respond with a 200 or 201. If your server responds with a 403, the user will be automatically unsubscribed. All other error codes will be retried up-to a predefined maximum attempts.
Verifying Webhook Requests
Every webhook request carries three headers that let you confirm it came from FitnessSyncer and has not been altered or replayed:
- X-FitnessSyncer-Timestamp: the time the request was signed, in seconds since the Unix epoch.
- X-FitnessSyncer-Signature-256: the Base64-encoded HMAC-SHA256 of the timestamp, a period, and the exact bytes of the request body as received, using your OAuth2 Secret Key as the key.
- X-FitnessSyncer-Signature: the Base64-encoded HMAC-SHA1 of the URL-encoded context body part, using your OAuth2 Secret Key as the key. This covers only the context part, not the item, JSON or file, and is kept unchanged for compatibility with existing integrations.
We recommend verifying X-FitnessSyncer-Signature-256. To do so:
- Read the raw request body before any multipart or form parsing, since parsing and re-serializing the body will not reproduce the bytes that were signed.
- Compute the HMAC-SHA256 of the X-FitnessSyncer-Timestamp value, followed by a period (.), followed by the raw body, keyed by your OAuth2 Secret Key, and Base64-encode the result.
- Compare your result with X-FitnessSyncer-Signature-256 using a constant-time comparison, such as
hmac.compare_digestin Python,crypto.timingSafeEqualin Node.js orMessageDigest.isEqualin Java, and reject the request if they differ. - Reject the request if the timestamp is more than 5 minutes older or newer than your server’s clock, so a captured request cannot be replayed later.
Learning if there is a subscription
To figure out if there is an active subscription, use this method. You may periodically wish to do this in the event of errors notifying your service of a subscription.
The data will be filtered based on the scopes provided; not all of the scopes listed are required.
Example request
curl -H "Authorization: Bearer AccessToken" "https://api.fitnesssyncer.com/api/subscriptions/"Request Parameters
None
Response
The response to this query will be a JSON object with Subscription.
If there is not an active subscription, the response will be a 404.
Sample
{"notificationKey": "1bd2a05e-7c1e-40fc-b3de-57f0b1672861"}Subscribing
To subscribe a user for notifications, you can use this API.
The data will be filtered based on the scopes provided; not all of the scopes listed are required.
Request Parameters
None
Response
The response to this query will be a JSON object with Subscription.
Sample
{"notificationKey": "1bd2a05e-7c1e-40fc-b3de-57f0b1672861"}Unsubscribing
To unsubscribe a user from notifications, use this endpoint.
Note that if your server responds with a 403 error when it is notified, they will be automatically unsubscribed.
Unsubscribe a user as part of deregistering them such as when they stop using your application, or delete their account with you, along with revoking their token.
The data will be filtered based on the scopes provided; not all of the scopes listed are required.
Example request
curl -X DELETE -H "Authorization: Bearer AccessToken" "https://api.fitnesssyncer.com/api/subscriptions/notificationKey"Request Parameters
None
Response
The response to this query will be a JSON object with a status indicating success.
Sample
{"status": "OK"}Pull Notifications: Claiming Notifications
For pull notifications, you will need to claim notifications, process the notifications, and then delete the claim. If you do not delete the claim, the notification will eventually come back to you.
Note that we will only provide you with a maximum of 100 notifications per response. If you have more than 100 notifications, you will need to requery the API for each notification.
The data will be filtered based on the scopes provided; not all of the scopes listed are required.
Request Parameters
None
Response
If the response code is a 204, there currently are no notifications available.
If the response code is a 200, the body of the JSON object will have Notification result.
Sample
{
"claim": "1bd2a05e-7c1e-40fc-b3de-57f0b1672861",
"notifications": {
"items": [{
"notificationKey": "1bd2a05e-7c1e-40fc-b3de-57f0b1672861",
"sourceId": "b16e8e9c-0f44-48a4-a717-1ca12c0d959a",
"itemId": "1762710031"
}],
"errors": []
}
}Pull Notifications: Deleting Notifications
Once you have successfully processed a notification, you must delete it. Failure to do so will result in the same notification being delivered to you again.
The data will be filtered based on the scopes provided; not all of the scopes listed are required.
Example request
curl -X DELETE -H "Authorization: Bearer AccessToken" "https://api.fitnesssyncer.com/api/notifications/claim"Request Parameters
None
Response
The response to this query will be a JSON object with a status indicating success.
Sample
{"status": "OK"}Types
Subscription
| JSON Item | Data Type | Description |
|---|---|---|
| notificationKey | String | The notification key for the subscription. This notificationKey will be in each of the notifications executed to your service on behalf of this user. Repeating queries here will result in new keys being created. |
Notification
| JSON Item | Data Type | Description |
|---|---|---|
| claim | String | The claim will be required for deleting the notification. |
| notifications | Notifications |
Notifications
| JSON Item | Data Type | Description |
|---|---|---|
| items | Array of Notification Item | List of the subscriptions, source id, and item id. |
| errors | Array of Notification Error Item | List of the subscriptions which have encountered one or more errors. |
Notification Item
| JSON Item | Data Type | Description |
|---|---|---|
| notificationKey | String | Subscription Id to look up the user. |
| sourceId | String | Source Id of the item which has been updated. |
| itemId | String | Item Id of the item which has been updated. |
Notification Error Item
| JSON Item | Data Type | Description |
|---|---|---|
| notificationKey | String | Subscription Id to look up the user. |
| error | String | Locale-based error message. |
| providerType | String | An enumeration of the Provider Type for uploading data to this API. |
| sourceId | String | Source Id of the item which has been updated (if applicable) |
| destinationId | String | Source Id of the item which has been updated (if applicable) |