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)