Skip to main content
Webhooks allow you to receive real-time notifications when new health data arrives from connected wearables, instead of constantly polling the API. Open Wearables automatically handles provider webhooks and can forward events to your application.

How Webhooks Work

1

Provider sends data

When a user syncs their device (e.g., Garmin watch), the provider sends a webhook to Open Wearables with new data.
2

Open Wearables processes data

Open Wearables receives the webhook, validates it, fetches the full data, and stores it in the database.
3

Your webhook is triggered

Open Wearables forwards a notification to your configured webhook endpoint with details about what data was updated.
4

You fetch the data

Your application receives the webhook and can immediately query the relevant API endpoints to get the new data.

Supported Provider Webhooks

Garmin

Garmin webhooks are automatically configured when you connect a user. No additional setup required.
PUSH Webhooks - Receive inline data:
  • Activities (with metadata)
  • Sleep sessions
  • Daily summaries
  • Heart rate variability
  • Stress details
  • Body composition
  • Blood pressure
  • And 10+ other data types
PING Webhooks - Receive callback URLs to fetch data:
  • Same data types as PUSH
  • Used for larger payloads
Permission Changes:
  • User updates data sharing permissions on Garmin Connect
  • Connection scope is automatically updated
Deregistrations:
  • User removes app from Garmin Connect
  • Connection is marked as revoked

Strava

Activity Webhooks:
  • New activities created
  • Activities updated
  • Activities deleted

Whoop

Real-time Updates:
  • Recovery scores
  • Sleep analysis
  • Strain measurements

Webhook Payload Format

When Open Wearables forwards a webhook to your application, it sends:
{
  "event": "data.updated",
  "timestamp": "2026-03-07T10:30:00Z",
  "user_id": "550e8400-e29b-41d4-a716-446655440000",
  "provider": "garmin",
  "data_types": ["workout", "sleep", "daily_summary"],
  "metadata": {
    "activities_count": 1,
    "sleep_sessions_count": 1,
    "trace_id": "abc123"
  }
}
Fields:
event
string
Event type (currently only data.updated)
timestamp
datetime
When the webhook was generated (ISO 8601)
user_id
UUID
Open Wearables user ID
provider
string
Source provider: garmin, whoop, strava, etc.
data_types
array
Types of data that were updated: workout, sleep, daily_summary, heart_rate, etc.
metadata
object
Additional context about the update (varies by provider)

Configuring Your Webhook Endpoint

1

Create an endpoint

Set up an HTTPS endpoint in your application to receive webhooks:
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/webhooks/openwearables', methods=['POST'])
def handle_webhook():
    payload = request.json
    
    # Verify signature (recommended)
    signature = request.headers.get('X-OpenWearables-Signature')
    if not verify_signature(signature, request.data):
        return jsonify({'error': 'Invalid signature'}), 401
    
    # Process the webhook
    user_id = payload['user_id']
    data_types = payload['data_types']
    
    # Queue a job to fetch new data
    fetch_user_data.delay(user_id, data_types)
    
    return jsonify({'status': 'received'}), 200
2

Register your endpoint

Configure your webhook URL in the Open Wearables dashboard:
  1. Go to Settings → Webhooks
  2. Enter your endpoint URL (must be HTTPS)
  3. Select which events to receive
  4. Save your webhook configuration
3

Test the webhook

Use the “Send Test Webhook” button in the dashboard to verify your endpoint is working correctly.

Webhook Security

Signature Verification

Each webhook includes an X-OpenWearables-Signature header with an HMAC signature. Verify this to ensure the webhook came from Open Wearables:
import hmac
import hashlib

def verify_signature(signature: str, payload: bytes, secret: str) -> bool:
    """Verify webhook signature."""
    expected = hmac.new(
        secret.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()
    
    return hmac.compare_digest(signature, expected)

# Usage
webhook_secret = 'your_webhook_secret_from_dashboard'
is_valid = verify_signature(
    request.headers['X-OpenWearables-Signature'],
    request.data,
    webhook_secret
)
Always verify webhook signatures before processing the payload. This prevents malicious actors from sending fake webhooks to your endpoint.

Best Practices

  1. Use HTTPS: Webhook URLs must use HTTPS in production
  2. Verify signatures: Always validate the X-OpenWearables-Signature header
  3. Respond quickly: Return 200 status within 5 seconds
  4. Process asynchronously: Queue webhook processing to avoid timeouts
  5. Handle idempotency: Same data may trigger multiple webhooks
  6. Log failures: Keep audit logs for debugging

Webhook Response Requirements

Your endpoint must respond with a 2xx status code within 5 seconds. If Open Wearables doesn’t receive a successful response, it will retry with exponential backoff.
Successful response:
{
  "status": "received"
}
Error response (will trigger retry):
{
  "error": "Temporary processing error"
}

Retry Policy

If your endpoint fails or times out:
  1. Immediate retry after 1 second
  2. Second retry after 5 seconds
  3. Third retry after 25 seconds
  4. Fourth retry after 2 minutes
  5. Fifth retry after 10 minutes
  6. Disabled after 5 consecutive failures
You can view retry attempts and re-enable webhooks in the dashboard.

Processing Webhook Data

After receiving a webhook, fetch the new data:
import requests

def process_webhook(payload):
    user_id = payload['user_id']
    data_types = payload['data_types']
    
    api_key = 'YOUR_API_KEY'
    base_url = 'https://api.openwearables.com/api/v1'
    headers = {'Authorization': f'Bearer {api_key}'}
    
    # Fetch new workouts if workout data was updated
    if 'workout' in data_types:
        # Get workouts from last 24 hours
        from datetime import datetime, timedelta
        end = datetime.utcnow()
        start = end - timedelta(days=1)
        
        response = requests.get(
            f'{base_url}/users/{user_id}/events/workouts',
            params={
                'start_date': start.isoformat(),
                'end_date': end.isoformat(),
                'limit': 50
            },
            headers=headers
        )
        
        workouts = response.json()['data']
        # Process workouts...
    
    # Fetch new sleep data if sleep was updated
    if 'sleep' in data_types:
        # Similar approach for sleep data
        pass

Webhook Events Reference

EventDescriptionData Types
data.updatedNew data received from providerworkout, sleep, daily_summary, heart_rate, body_composition
connection.revokedUser disconnected wearableN/A
connection.errorProvider sync errorN/A

Testing Webhooks

Local Development

Use a tool like ngrok to expose your local server:
# Start your local server
python app.py  # runs on localhost:5000

# In another terminal, start ngrok
ngrok http 5000

# Use the ngrok HTTPS URL in Open Wearables dashboard
# Example: https://abc123.ngrok.io/webhooks/openwearables

Testing Tools

  • Dashboard: Use “Send Test Webhook” button
  • curl: Manually send test payloads
  • Postman: Create webhook collections for testing
curl -X POST https://your-app.com/webhooks/openwearables \
  -H "Content-Type: application/json" \
  -H "X-OpenWearables-Signature: test_signature" \
  -d '{
    "event": "data.updated",
    "timestamp": "2026-03-07T10:30:00Z",
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "provider": "garmin",
    "data_types": ["workout"]
  }'

Monitoring Webhooks

The Open Wearables dashboard provides:
  • Delivery logs: See all webhook attempts and responses
  • Failure alerts: Get notified when webhooks fail
  • Retry history: View retry attempts and timing
  • Performance metrics: Track webhook latency and success rates

Troubleshooting

Webhooks not received

  • Verify your endpoint URL is correct and accessible from the internet
  • Check that your server is responding within 5 seconds
  • Ensure your endpoint accepts POST requests
  • Verify SSL certificate is valid

Duplicate webhooks

  • Implement idempotency using the trace_id in metadata
  • Store processed webhook IDs to avoid duplicate processing

Missing data in webhook

  • Webhooks are notifications, not full data payloads
  • Always query the API to get the actual data
  • Account for small delays between webhook and data availability

Next Steps

Authentication

Learn about API keys and SDK tokens

API Reference

Complete API endpoint documentation

Build docs developers (and LLMs) love