Files
reflector/server/docs/webhook.md
Mathieu Virbel 88ed7cfa78 feat(rooms): add webhook for transcript completion (#578)
* feat(rooms): add webhook notifications for transcript completion

- Add webhook_url and webhook_secret fields to rooms table
- Create Celery task with 24-hour retry window using exponential backoff
- Send transcript metadata, diarized text, topics, and summaries via webhook
- Add HMAC signature verification for webhook security
- Add test endpoint POST /v1/rooms/{room_id}/webhook/test
- Update frontend with webhook configuration UI and test button
- Auto-generate webhook secret if not provided
- Trigger webhook after successful file pipeline processing for room recordings

* style: linting

* fix: remove unwanted files

* fix: update openapi gen

* fix: self-review

* docs: add comprehensive webhook documentation

- Document webhook configuration, events, and payloads
- Include transcript.completed and test event examples
- Add security considerations and best practices
- Provide example webhook receiver implementation
- Document retry policy and signature verification

* fix: remove audio_mp3_url from webhook payload

- Remove audio download URL generation from webhook
- Update documentation to reflect the change
- Keep only frontend_url for accessing transcripts

* docs: remove unwanted section

* fix: correct API method name and type imports for rooms

- Fix v1RoomsRetrieve to v1RoomsGet
- Update Room type to RoomDetails throughout frontend
- Fix type imports in useRoomList, RoomList, RoomTable, and RoomCards

* feat: add show/hide toggle for webhook secret field

- Add eye icon button to reveal/hide webhook secret when editing
- Show password dots when webhook secret is hidden
- Reset visibility state when opening/closing dialog
- Only show toggle button when editing existing room with secret

* fix: resolve event loop conflict in webhook test endpoint

- Extract webhook test logic into shared async function
- Call async function directly from FastAPI endpoint
- Keep Celery task wrapper for background processing
- Fixes RuntimeError: event loop already running

* refactor: remove unnecessary Celery task for webhook testing

- Webhook testing is synchronous and provides immediate feedback
- No need for background processing via Celery
- Keep only the async function called directly from API endpoint

* feat: improve webhook test error messages and display

- Show HTTP status code in error messages
- Parse JSON error responses to extract meaningful messages
- Improved UI layout for webhook test results
- Added colored background for success/error states
- Better text wrapping for long error messages

* docs: adjust doc

* fix: review

* fix: update attempts to match close 24h

* fix: add event_id

* fix: changed to uuid, to have new event_id when reprocess.

* style: linting

* fix: alembic revision
2025-08-29 10:07:49 -06:00

6.9 KiB

Reflector Webhook Documentation

Overview

Reflector supports webhook notifications to notify external systems when transcript processing is completed. Webhooks can be configured per room and are triggered automatically after a transcript is successfully processed.

Configuration

Webhooks are configured at the room level with two fields:

  • webhook_url: The HTTPS endpoint to receive webhook notifications
  • webhook_secret: Optional secret key for HMAC signature verification (auto-generated if not provided)

Events

transcript.completed

Triggered when a transcript has been fully processed, including transcription, diarization, summarization, and topic detection.

test

A test event that can be triggered manually to verify webhook configuration.

Webhook Request Format

Headers

All webhook requests include the following headers:

Header Description Example
Content-Type Always application/json application/json
User-Agent Identifies Reflector as the source Reflector-Webhook/1.0
X-Webhook-Event The event type transcript.completed or test
X-Webhook-Retry Current retry attempt number 0, 1, 2...
X-Webhook-Signature HMAC signature (if secret configured) t=1735306800,v1=abc123...

Signature Verification

If a webhook secret is configured, Reflector includes an HMAC-SHA256 signature in the X-Webhook-Signature header to verify the webhook authenticity.

The signature format is: t={timestamp},v1={signature}

To verify the signature:

  1. Extract the timestamp and signature from the header
  2. Create the signed payload: {timestamp}.{request_body}
  3. Compute HMAC-SHA256 of the signed payload using your webhook secret
  4. Compare the computed signature with the received signature

Example verification (Python):

import hmac
import hashlib

def verify_webhook_signature(payload: bytes, signature_header: str, secret: str) -> bool:
    # Parse header: "t=1735306800,v1=abc123..."
    parts = dict(part.split("=") for part in signature_header.split(","))
    timestamp = parts["t"]
    received_signature = parts["v1"]

    # Create signed payload
    signed_payload = f"{timestamp}.{payload.decode('utf-8')}"

    # Compute expected signature
    expected_signature = hmac.new(
        secret.encode("utf-8"),
        signed_payload.encode("utf-8"),
        hashlib.sha256
    ).hexdigest()

    # Compare signatures
    return hmac.compare_digest(expected_signature, received_signature)

Event Payloads

transcript.completed Event

This event includes a convenient URL for accessing the transcript:

  • frontend_url: Direct link to view the transcript in the web interface
{
  "event": "transcript.completed",
  "event_id": "transcript.completed-abc-123-def-456",
  "timestamp": "2025-08-27T12:34:56.789012Z",
  "transcript": {
    "id": "abc-123-def-456",
    "room_id": "room-789",
    "created_at": "2025-08-27T12:00:00Z",
    "duration": 1800.5,
    "title": "Q3 Product Planning Meeting",
    "short_summary": "Team discussed Q3 product roadmap, prioritizing mobile app features and API improvements.",
    "long_summary": "The product team met to finalize the Q3 roadmap. Key decisions included...",
    "webvtt": "WEBVTT\n\n00:00:00.000 --> 00:00:05.000\n<v Speaker 1>Welcome everyone to today's meeting...",
    "topics": [
      {
        "title": "Introduction and Agenda",
        "summary": "Meeting kickoff with agenda review",
        "timestamp": 0.0,
        "duration": 120.0,
        "webvtt": "WEBVTT\n\n00:00:00.000 --> 00:00:05.000\n<v Speaker 1>Welcome everyone..."
      },
      {
        "title": "Mobile App Features Discussion",
        "summary": "Team reviewed proposed mobile app features for Q3",
        "timestamp": 120.0,
        "duration": 600.0,
        "webvtt": "WEBVTT\n\n00:02:00.000 --> 00:02:10.000\n<v Speaker 2>Let's talk about the mobile app..."
      }
    ],
    "participants": [
      {
        "id": "participant-1",
        "name": "John Doe",
        "speaker": "Speaker 1"
      },
      {
        "id": "participant-2",
        "name": "Jane Smith",
        "speaker": "Speaker 2"
      }
    ],
    "source_language": "en",
    "target_language": "en",
    "status": "completed",
    "frontend_url": "https://app.reflector.com/transcripts/abc-123-def-456"
  },
  "room": {
    "id": "room-789",
    "name": "Product Team Room"
  }
}

test Event

{
  "event": "test",
  "event_id": "test.2025-08-27T12:34:56.789012Z",
  "timestamp": "2025-08-27T12:34:56.789012Z",
  "message": "This is a test webhook from Reflector",
  "room": {
    "id": "room-789",
    "name": "Product Team Room"
  }
}

Retry Policy

Webhooks are delivered with automatic retry logic to handle transient failures. When a webhook delivery fails due to server errors or network issues, Reflector will automatically retry the delivery multiple times over an extended period.

Retry Mechanism

Reflector implements an exponential backoff strategy for webhook retries:

  • Initial retry delay: 60 seconds after the first failure
  • Exponential backoff: Each subsequent retry waits approximately twice as long as the previous one
  • Maximum retry interval: 1 hour (backoff is capped at this duration)
  • Maximum retry attempts: 30 attempts total
  • Total retry duration: Retries continue for approximately 24 hours

How Retries Work

When a webhook fails, Reflector will:

  1. Wait 60 seconds, then retry (attempt #1)
  2. If it fails again, wait ~2 minutes, then retry (attempt #2)
  3. Continue doubling the wait time up to a maximum of 1 hour between attempts
  4. Keep retrying at 1-hour intervals until successful or 30 attempts are exhausted

The X-Webhook-Retry header indicates the current retry attempt number (0 for the initial attempt, 1 for first retry, etc.), allowing your endpoint to track retry attempts.

Retry Behavior by HTTP Status Code

Status Code Behavior
2xx (Success) No retry, webhook marked as delivered
4xx (Client Error) No retry, request is considered permanently failed
5xx (Server Error) Automatic retry with exponential backoff
Network/Timeout Error Automatic retry with exponential backoff

Important Notes:

  • Webhooks timeout after 30 seconds. If your endpoint takes longer to respond, it will be considered a timeout error and retried.
  • During the retry period (~24 hours), you may receive the same webhook multiple times if your endpoint experiences intermittent failures.
  • There is no mechanism to manually retry failed webhooks after the retry period expires.

Testing Webhooks

You can test your webhook configuration before processing transcripts:

POST /v1/rooms/{room_id}/webhook/test

Response:

{
  "success": true,
  "status_code": 200,
  "message": "Webhook test successful",
  "response_preview": "OK"
}

Or in case of failure:

{
  "success": false,
  "error": "Webhook request timed out (10 seconds)"
}