as

Settings
Sign out
Notifications
Alexa
Amazon Appstore
Ring
AWS
Documentation
Support
Contact Us
My Cases
Ring

Notifications

Ring provides real-time notifications to partners through webhook-based callbacks. This enables partners to receive timely updates about device events, changes, and user actions.

Overview

The notification system uses:

  • HTTP POST webhooks to partner endpoints
  • HMAC-SHA256 signature in the X-Signature header for message authenticity
  • JSON:API structure for consistent payload format
  • Event-driven architecture for real-time updates
  • Account ID in meta for user association

Webhook Endpoint Requirements

Before receiving webhooks, your endpoint must meet the following requirements:

Requirement Detail
Protocol HTTPS only (TLS 1.2 or higher required)
Accessibility Endpoint must be publicly accessible from Ring's servers
Registration Webhook URL is configured during partner onboarding
Response time Must respond within 5 seconds or Ring treats the delivery as failed
Content-Type Ring sends application/json; your endpoint must accept this content type
Method Ring sends POST requests exclusively

Webhook Authentication & Verification

HMAC-SHA256 Signature Verification

All webhook requests from Ring include an HMAC-SHA256 signature in the X-Signature header. Partners must verify this signature using the HMAC signing key issued with their partner credentials before processing any webhook payload:

POST https://api.partner.example.com/webhooks/ring
X-Signature: sha256=<hmac_signature>
Content-Type: application/json

Signature Verification

import hmac
import hashlib

def verify_webhook_signature(signing_key, raw_body, received_signature):
    """Verify the HMAC-SHA256 signature of a Ring webhook."""
    expected = hmac.new(
        signing_key.encode(),
        raw_body,
        hashlib.sha256
    ).hexdigest()

    received = received_signature.removeprefix("sha256=")

    # Constant-time comparison to prevent timing attacks
    return hmac.compare_digest(expected, received)

Webhook v1.1 Payload Structure

All Ring webhooks follow the v1.1 payload format with account_id in the meta section:

{
  "meta": {
    "version": "1.1",
    "time": "2026-02-13T13:39:57.200155525Z",
    "request_id": "2ad45ade-1818-4154-813b-afdd8bcd8085",
    "account_id": "ava1.ring.account.XXXYYY"
  },
  "data": {
    "id": "<device_id>_<event_type>_<timestamp>",
    "type": "<event_type>",
    "attributes": {
      "source": "<device_id>",
      "source_type": "devices",
      "timestamp": 1770989995231
    },
    "relationships": {
      "devices": {
        "links": {
          "self": "/v1/devices/<device_id>"
        }
      }
    }
  }
}

Meta Fields

  • version: Always 1.1 for the current webhook specification
  • time: ISO 8601 timestamp when Ring sent the webhook
  • request_id: Unique identifier for this webhook request (use for idempotency)
  • account_id: The Account ID of the Ring user associated with this event

Event Types

Ring supports the following webhook event types:

Event Type Value Description Details
Motion Detected motion_detected Motion detected by a device camera (includes subType such as human) Motion Detection
Button Press button_press Ring doorbell button pressed Button Press
Device Added device_added A device became accessible to the partner Device Addition
Device Removed device_removed A device is no longer accessible Device Removal
Device Online device_online A device came online Device Online
Device Offline device_offline A device went offline Device Offline

Webhook Response Handling

Your endpoint must respond with an appropriate HTTP status code:

Status Code Ring Behavior Details
200-299 Delivery successful Ring marks the event as delivered. No retry.
400-499 Permanent failure — no retry Indicates a client-side issue. Ring will not retry these.
500-599 Temporary failure — retry with backoff Ring will retry delivery using exponential backoff.
Timeout Treated as 5xx — retry with backoff If your endpoint does not respond within 5 seconds, Ring treats it as a server error.

Retry Logic

Ring implements automatic retry logic for failed webhook deliveries (5xx responses and timeouts):

Retry Schedule

Attempt Delay After Previous Attempt
1 (initial) Immediate
2 1 second
3 5 seconds
4 30 seconds
5 2 minutes
6 10 minutes
7 1 hour
  • Maximum retry attempts: 6 retries (7 total attempts including the initial delivery)
  • Dead letter queue: After all retries are exhausted, the event is moved to a dead letter queue. Events are retained for 72 hours. Partners can request a replay of dead-lettered events by contacting their Ring integration representative.

Implementation Best Practices

Webhook Handler Example

from flask import Flask, request, jsonify
import hmac
import hashlib

app = Flask(__name__)

SIGNING_KEY = "your_hmac_signing_key"

@app.route('/webhook/ring', methods=['POST'])
def handle_ring_webhook():
    # Verify HMAC signature
    signature = request.headers.get('X-Signature', '')
    if not verify_webhook_signature(SIGNING_KEY, request.data, signature):
        return jsonify({'error': 'Invalid signature'}), 401

    # Parse payload
    try:
        payload = request.get_json()
        event_type = payload['data']['type']
        account_id = payload['meta']['account_id']

        # Route to appropriate handler
        if event_type == 'motion_detected':
            handle_motion_detection(payload)
        elif event_type == 'button_press':
            handle_button_press(payload)
        elif event_type == 'device_added':
            handle_device_addition(payload)
        elif event_type == 'device_removed':
            handle_device_removal(payload)
        elif event_type == 'device_online':
            handle_device_online(payload)
        elif event_type == 'device_offline':
            handle_device_offline(payload)
        else:
            return jsonify({'error': 'Unknown event type'}), 400

        return jsonify({'status': 'processed'}), 200

    except Exception as e:
        log_error(f"Webhook processing failed: {e}")
        return jsonify({'error': 'Processing failed'}), 500

Idempotency Handling

def handle_webhook_with_idempotency(payload):
    request_id = payload['meta']['request_id']

    if is_already_processed(request_id):
        return {'status': 'already_processed'}

    result = process_webhook(payload)
    mark_as_processed(request_id)
    return result

Common Mistakes

Mistake Consequence Fix
Not verifying HMAC signatures Accepts spoofed webhooks Always call verify_webhook_signature() before processing
Doing heavy processing in handler Exceeds 5-second timeout, causes duplicates Return 200 immediately, process asynchronously
Not handling duplicate events Business logic executes multiple times Use meta.request_id as idempotency key
Returning 4xx for transient errors Ring will not retry Return 500 for recoverable errors
Ignoring dead letter queue Missed events during outages Monitor and request replays within 72-hour window

Security Considerations

  1. Verify HMAC signature: Always validate the X-Signature header
  2. Use account_id: Associate events with the correct Ring user via meta.account_id
  3. Validate payload: Check request structure and required fields
  4. Idempotency: Handle duplicate deliveries gracefully using request_id
  5. Rate limiting: Implement appropriate rate limiting on webhook endpoints
  6. Respond quickly: Return HTTP 200 within 5 seconds

Next: Users API →