Skip to main content
Home›Docs›Webhooks›Webhooks overview
Webhooks

Webhooks overview

Register and consume HTTP push notifications for analysis completion and failures.

Webhooks overview

Perceive8 can send HTTP POST notifications to your endpoints when audio analysis jobs complete or fail. This eliminates the need for polling and lets you react to results immediately.

Registering a webhook

Register a URL to receive events using the POST /v1/webhooks endpoint.

curl -X POST https://api.perceive8.com/v1/webhooks \
  -H "X-API-Key: pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.example.com/webhooks/perceive8",
    "events": ["analysis.completed", "analysis.failed"]
  }'

Response:

{
  "id": "webhook-uuid",
  "url": "https://yourapp.example.com/webhooks/perceive8",
  "events": ["analysis.completed", "analysis.failed"],
  "created_at": "2024-01-15T10:00:00Z"
}

Event types

Event Fired when
analysis.completed An audio analysis pipeline finishes successfully
analysis.failed An audio analysis pipeline fails

Webhook payload shapes

All webhooks are sent as HTTP POST with Content-Type: application/json.

analysis.completed

Fired when an analysis reaches completed status and the full transcript and intelligence data are available.

{
  "event": "analysis.completed",
  "analysis_id": "550e8400-e29b-41d4-a716-446655440000",
  "user_id": "user-uuid",
  "filename": "meeting.mp3",
  "status": "completed",
  "created_at": "2024-01-15T10:00:00Z",
  "completed_at": "2024-01-15T10:03:45Z",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "user_id": "user-uuid",
    "filename": "meeting.mp3",
    "status": "completed",
    "created_at": "2024-01-15T10:00:00Z",
    "completed_at": "2024-01-15T10:03:45Z",
    "transcript": {
      "text": "Hello. Good morning. Let's talk about Q4 targets...",
      "segments": [
        {
          "text": "Hello.",
          "speaker_label": "Speaker A",
          "start_time": 0.5,
          "end_time": 1.0,
          "confidence": 0.99,
          "words": [
            { "text": "Hello", "start": 0.5, "end": 0.9, "confidence": 0.99 }
          ]
        }
      ]
    },
    "summary": "A business meeting discussing Q4 revenue targets and actionable milestones.",
    "topics": ["Q4", "revenue", "targets", "milestones"],
    "entities": [
      { "text": "ACME Corp", "entity_type": "ORG" },
      { "text": "Sarah", "entity_type": "PERSON" }
    ],
    "sentiment": "positive",
    "speaker_count": 2
  }
}

analysis.failed

Fired when an analysis reaches failed status.

{
  "event": "analysis.failed",
  "analysis_id": "550e8400-e29b-41d4-a716-446655440001",
  "user_id": "user-uuid",
  "filename": "corrupted.mp3",
  "status": "failed",
  "created_at": "2024-01-15T11:00:00Z",
  "completed_at": "2024-01-15T11:00:15Z",
  "error": "Audio file could not be decoded"
}

Security verification

Every webhook includes a signature header so you can verify it came from Perceive8. See Verifying webhook signatures for examples.

Retry behavior

Perceive8 makes up to five delivery attempts with a scheduled backoff. See Retry behavior for the full schedule and best practices.

Testing webhooks locally

For local development, use a tunnel service to expose your local server.

With ngrok

ngrok http 3000
# Use the generated URL: https://abc123.ngrok.io/webhooks/perceive8

With smee.io

npx smee-client --url https://smee.io/your-channel --path /webhooks/perceive8 --port 3000

Then register the tunnel URL as your webhook endpoint.

Managing webhooks via SDK

Webhook CRUD is currently done via direct HTTP calls rather than the SDK resource layer.

JavaScript / TypeScript

// List webhooks
const res = await fetch("https://api.perceive8.com/v1/webhooks", {
  headers: { "X-API-Key": process.env.PERCEIVE8_API_KEY! },
});
const webhooks = await res.json();

// Create a webhook
const createRes = await fetch("https://api.perceive8.com/v1/webhooks", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.PERCEIVE8_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://yourapp.example.com/webhooks/perceive8",
    events: ["analysis.completed", "analysis.failed"],
  }),
});
const webhook = await createRes.json();

// Delete a webhook
await fetch(`https://api.perceive8.com/v1/webhooks/${webhook.id}`, {
  method: "DELETE",
  headers: { "X-API-Key": process.env.PERCEIVE8_API_KEY! },
});

Python

import httpx

BASE_URL = "https://api.perceive8.com"
API_KEY = "pk_live_xxxx"
headers = {"X-API-Key": API_KEY}

# List webhooks
r = httpx.get(f"{BASE_URL}/v1/webhooks", headers=headers)
webhooks = r.json()

# Create a webhook
r = httpx.post(
    f"{BASE_URL}/v1/webhooks",
    headers={**headers, "Content-Type": "application/json"},
    json={
        "url": "https://yourapp.example.com/webhooks/perceive8",
        "events": ["analysis.completed", "analysis.failed"],
    },
)
webhook = r.json()
print("Created webhook:", webhook["id"])

# Delete a webhook
httpx.delete(f"{BASE_URL}/v1/webhooks/{webhook['id']}", headers=headers)