{"id":"bdb43f8d-16d5-4974-9645-8f6fd3703121","shortId":"QCuh2f","kind":"skill","title":"elevenlabs-webhooks","tagline":"Receive and verify ElevenLabs webhooks. Use when setting up ElevenLabs webhook handlers, debugging signature verification, or handling call transcription events.","description":"# ElevenLabs Webhooks\n\n## When to Use This Skill\n\n- Setting up ElevenLabs webhook handlers\n- Debugging signature verification failures\n- Understanding ElevenLabs event types and payloads\n- Processing call transcription events\n- Handling voice removal notifications\n\n## Essential Code\n\n### Signature Verification (SDK — Recommended)\n\nElevenLabs recommends using the official `@elevenlabs/elevenlabs-js` SDK for webhook verification and event construction. See [Verify the webhook secret and construct the webhook payload](https://elevenlabs.io/docs/agents-platform/guides/integrations/upstash-redis#verify-the-webhook-secret-and-consrtuct-the-webhook-payload).\n\n```javascript\n// Express.js / Node example\nconst { ElevenLabsClient } = require('@elevenlabs/elevenlabs-js');\n\nconst elevenlabs = new ElevenLabsClient({\n  apiKey: process.env.ELEVENLABS_API_KEY || 'webhook-only'\n});\n\n// In your webhook handler: get raw body and signature header, then:\nconst event = await elevenlabs.webhooks.constructEvent(rawBody, signatureHeader, process.env.ELEVENLABS_WEBHOOK_SECRET);\n// event is the parsed payload; SDK throws on invalid signature\n```\n\n```typescript\n// Next.js example\nimport { ElevenLabsClient } from '@elevenlabs/elevenlabs-js';\n\nconst elevenlabs = new ElevenLabsClient({\n  apiKey: process.env.ELEVENLABS_API_KEY || 'webhook-only'\n});\n\nexport async function POST(request: NextRequest) {\n  const rawBody = await request.text();\n  const signatureHeader = request.headers.get('ElevenLabs-Signature');\n  try {\n    const event = await elevenlabs.webhooks.constructEvent(\n      rawBody,\n      signatureHeader,\n      process.env.ELEVENLABS_WEBHOOK_SECRET\n    );\n    // Handle event.type, event.data...\n    return new NextResponse('OK', { status: 200 });\n  } catch (error) {\n    return NextResponse.json({ error: (error as Error).message }, { status: 401 });\n  }\n}\n```\n\n### Python SDK Verification (FastAPI)\n\n```python\nimport os\nfrom fastapi import FastAPI, Request, HTTPException\nfrom elevenlabs import ElevenLabs\nfrom elevenlabs.errors import BadRequestError\n\napp = FastAPI()\nelevenlabs = ElevenLabs(api_key=os.environ.get(\"ELEVENLABS_API_KEY\") or \"webhook-only\")\n\n@app.post(\"/webhooks/elevenlabs\")\nasync def elevenlabs_webhook(request: Request):\n    raw_body = await request.body()\n    sig = request.headers.get(\"ElevenLabs-Signature\") or request.headers.get(\"elevenlabs-signature\")\n    \n    if not sig:\n        raise HTTPException(status_code=400, detail=\"Missing signature header\")\n    \n    try:\n        event = elevenlabs.webhooks.construct_event(\n            raw_body.decode(\"utf-8\"),\n            sig,\n            os.environ[\"ELEVENLABS_WEBHOOK_SECRET\"]\n        )\n        # Handle event[\"type\"], event[\"data\"]...\n        return {\"status\": \"ok\"}\n    except BadRequestError as e:\n        raise HTTPException(status_code=401, detail=\"Invalid signature\")\n```\n\nThe SDK (Node/TypeScript and Python) verifies the signature, validates the timestamp (30-minute tolerance), and returns the parsed event. On failure it throws; return 401 and the error message.\n\n## Common Event Types\n\n| Event | Triggered When | Common Use Cases |\n|-------|----------------|------------------|\n| `post_call_transcription` | Call analysis completed | Process call insights, save transcripts |\n| `voice_removal_notice` | Notice that voice will be removed | Notify users, backup voice data |\n| `voice_removal_notice_withdrawn` | Voice removal notice cancelled | Update user notifications |\n| `voice_removed` | Voice has been removed | Clean up voice data, update UI |\n\n## Environment Variables\n\n```bash\nELEVENLABS_WEBHOOK_SECRET=your_webhook_secret_here\n```\n\n## Local Development\n\nFor local webhook testing, install Hookdeck CLI:\n\n```bash\n# Install via npm (recommended)\nnpm install -g hookdeck-cli\n\n# Or via Homebrew\nbrew install hookdeck/hookdeck/hookdeck\n```\n\nThen start the tunnel:\n\n```bash\nhookdeck listen 3000 --path /webhooks/elevenlabs\n```\n\nNo account required. Provides local tunnel + web UI for inspecting requests.\n\n## Resources\n\n- [Overview](references/overview.md) - What ElevenLabs webhooks are, common event types\n- [Setup](references/setup.md) - Configure webhooks in ElevenLabs dashboard, get signing secret\n- [Verification](references/verification.md) - Signature verification details and gotchas\n- [Express Example](examples/express/) - Complete Express.js implementation\n- [Next.js Example](examples/nextjs/) - Next.js App Router implementation\n- [FastAPI Example](examples/fastapi/) - Python FastAPI implementation\n\n## Recommended: webhook-handler-patterns\n\nWe recommend installing the [webhook-handler-patterns](https://github.com/hookdeck/webhook-skills/tree/main/skills/webhook-handler-patterns) skill alongside this one for handler sequence, idempotency, error handling, and retry logic. Key references (open on GitHub):\n\n- [Handler sequence](https://github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/handler-sequence.md) — Verify first, parse second, handle idempotently third\n- [Idempotency](https://github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/idempotency.md) — Prevent duplicate processing\n- [Error handling](https://github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/error-handling.md) — Return codes, logging, dead letter queues\n- [Retry logic](https://github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/retry-logic.md) — Provider retry schedules, backoff patterns\n\n## Related Skills\n\n- [stripe-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/stripe-webhooks) - Stripe payment webhook handling\n- [shopify-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/shopify-webhooks) - Shopify e-commerce webhook handling\n- [github-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/github-webhooks) - GitHub repository webhook handling\n- [resend-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/resend-webhooks) - Resend email webhook handling\n- [chargebee-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/chargebee-webhooks) - Chargebee billing webhook handling\n- [clerk-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/clerk-webhooks) - Clerk auth webhook handling\n- [openai-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/openai-webhooks) - OpenAI webhook handling\n- [paddle-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/paddle-webhooks) - Paddle billing webhook handling\n- [webhook-handler-patterns](https://github.com/hookdeck/webhook-skills/tree/main/skills/webhook-handler-patterns) - Handler sequence, idempotency, error handling, retry logic\n- [hookdeck-event-gateway](https://github.com/hookdeck/webhook-skills/tree/main/skills/hookdeck-event-gateway) - Webhook infrastructure that replaces your queue — guaranteed delivery, automatic retries, replay, rate limiting, and observability for your webhook handlers\n\n## Official ElevenLabs SDK Skills\n\nFor making API calls TO ElevenLabs (text-to-speech, transcription, agents), see the official [ElevenLabs Skills](https://github.com/elevenlabs/skills). This skill handles the opposite direction: receiving webhooks FROM ElevenLabs.\n\n> **SDK Warning:** Always use `@elevenlabs/elevenlabs-js` for JavaScript. Do not use `npm install elevenlabs` (that's an outdated v1.x package).","tags":["elevenlabs","webhooks","webhook","skills","hookdeck","agent-skills","ai-coding","api-integrations","event-driven","github-webhooks","llm-tools","shopify-webhooks"],"capabilities":["skill","source-hookdeck","skill-elevenlabs-webhooks","topic-agent-skills","topic-ai-coding","topic-api-integrations","topic-event-driven","topic-github-webhooks","topic-llm-tools","topic-shopify-webhooks","topic-stripe-webhooks","topic-webhook-security","topic-webhook-signatures","topic-webhooks"],"categories":["webhook-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/hookdeck/webhook-skills/elevenlabs-webhooks","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add hookdeck/webhook-skills","source_repo":"https://github.com/hookdeck/webhook-skills","install_from":"skills.sh"}},"qualityScore":"0.484","qualityRationale":"deterministic score 0.48 from registry signals: · indexed on github topic:agent-skills · 69 github stars · SKILL.md body (7,450 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-02T06:55:46.296Z","embedding":null,"createdAt":"2026-04-18T22:13:51.518Z","updatedAt":"2026-05-02T06:55:46.296Z","lastSeenAt":"2026-05-02T06:55:46.296Z","tsv":"'-8':274 '/docs/agents-platform/guides/integrations/upstash-redis#verify-the-webhook-secret-and-consrtuct-the-webhook-payload).':85 '/elevenlabs/skills).':709 '/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/error-handling.md)':546 '/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/handler-sequence.md)':527 '/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/idempotency.md)':538 '/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/retry-logic.md)':557 '/hookdeck/webhook-skills/tree/main/skills/chargebee-webhooks)':612 '/hookdeck/webhook-skills/tree/main/skills/clerk-webhooks)':622 '/hookdeck/webhook-skills/tree/main/skills/github-webhooks)':592 '/hookdeck/webhook-skills/tree/main/skills/hookdeck-event-gateway)':666 '/hookdeck/webhook-skills/tree/main/skills/openai-webhooks)':632 '/hookdeck/webhook-skills/tree/main/skills/paddle-webhooks)':641 '/hookdeck/webhook-skills/tree/main/skills/resend-webhooks)':602 '/hookdeck/webhook-skills/tree/main/skills/shopify-webhooks)':580 '/hookdeck/webhook-skills/tree/main/skills/stripe-webhooks)':570 '/hookdeck/webhook-skills/tree/main/skills/webhook-handler-patterns)':504,652 '/webhooks/elevenlabs':235,431 '200':187 '30':311 '3000':429 '400':263 '401':198,296,324 'account':433 'agent':701 'alongsid':506 'alway':722 'analysi':342 'api':100,148,224,228,692 'apikey':98,146 'app':220,480 'app.post':234 'async':154,236 'auth':624 'automat':675 'await':118,161,172,244 'backoff':561 'backup':360 'badrequesterror':219,289 'bash':388,405,426 'bill':614,643 'bodi':111,243 'brew':419 'call':21,47,339,341,345,693 'cancel':370 'case':337 'catch':188 'chargebe':608,613 'chargebee-webhook':607 'clean':380 'clerk':618,623 'clerk-webhook':617 'cli':404,415 'code':55,262,295,548 'commerc':584 'common':329,335,450 'complet':343,473 'configur':455 'const':90,94,116,142,159,163,170 'construct':72,79 'dashboard':459 'data':284,362,383 'dead':550 'debug':16,36 'def':237 'deliveri':674 'detail':264,297,467 'develop':397 'direct':715 'duplic':540 'e':291,583 'e-commerc':582 'elevenlab':2,7,13,24,33,41,60,95,143,167,213,215,222,223,227,238,249,254,277,389,447,458,687,695,705,719,732 'elevenlabs-signatur':166,248,253 'elevenlabs-webhook':1 'elevenlabs.errors':217 'elevenlabs.io':84 'elevenlabs.io/docs/agents-platform/guides/integrations/upstash-redis#verify-the-webhook-secret-and-consrtuct-the-webhook-payload).':83 'elevenlabs.webhooks.construct':270 'elevenlabs.webhooks.constructevent':119,173 'elevenlabs/elevenlabs-js':65,93,141,724 'elevenlabscli':91,97,139,145 'email':604 'environ':386 'error':189,192,193,195,327,513,542,656 'essenti':54 'event':23,42,49,71,117,125,171,269,271,281,283,318,330,332,451,662 'event.data':181 'event.type':180 'exampl':89,137,471,477,484 'examples/express':472 'examples/fastapi':485 'examples/nextjs':478 'except':288 'export':153 'express':470 'express.js':87,474 'failur':39,320 'fastapi':202,207,209,221,483,487 'first':529 'function':155 'g':412 'gateway':663 'get':109,460 'github':522,588,593 'github-webhook':587 'github.com':503,526,537,545,556,569,579,591,601,611,621,631,640,651,665,708 'github.com/elevenlabs/skills).':707 'github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/error-handling.md)':544 'github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/handler-sequence.md)':525 'github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/idempotency.md)':536 'github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/retry-logic.md)':555 'github.com/hookdeck/webhook-skills/tree/main/skills/chargebee-webhooks)':610 'github.com/hookdeck/webhook-skills/tree/main/skills/clerk-webhooks)':620 'github.com/hookdeck/webhook-skills/tree/main/skills/github-webhooks)':590 'github.com/hookdeck/webhook-skills/tree/main/skills/hookdeck-event-gateway)':664 'github.com/hookdeck/webhook-skills/tree/main/skills/openai-webhooks)':630 'github.com/hookdeck/webhook-skills/tree/main/skills/paddle-webhooks)':639 'github.com/hookdeck/webhook-skills/tree/main/skills/resend-webhooks)':600 'github.com/hookdeck/webhook-skills/tree/main/skills/shopify-webhooks)':578 'github.com/hookdeck/webhook-skills/tree/main/skills/stripe-webhooks)':568 'github.com/hookdeck/webhook-skills/tree/main/skills/webhook-handler-patterns)':502,650 'gotcha':469 'guarante':673 'handl':20,50,179,280,514,532,543,574,586,596,606,616,626,635,645,657,712 'handler':15,35,108,492,500,510,523,648,653,685 'header':114,267 'homebrew':418 'hookdeck':403,414,427,661 'hookdeck-c':413 'hookdeck-event-gateway':660 'hookdeck/hookdeck/hookdeck':421 'httpexcept':211,260,293 'idempot':512,533,535,655 'implement':475,482,488 'import':138,204,208,214,218 'infrastructur':668 'insight':346 'inspect':441 'instal':402,406,411,420,496,731 'invalid':133,298 'javascript':86,726 'key':101,149,225,229,518 'letter':551 'limit':679 'listen':428 'local':396,399,436 'log':549 'logic':517,554,659 'make':691 'messag':196,328 'minut':312 'miss':265 'new':96,144,183 'next.js':136,476,479 'nextrequest':158 'nextrespons':184 'nextresponse.json':191 'node':88 'node/typescript':302 'notic':351,352,365,369 'notif':53,373 'notifi':358 'npm':408,410,730 'observ':681 'offici':64,686,704 'ok':185,287 'one':508 'open':520 'openai':628,633 'openai-webhook':627 'opposit':714 'os':205 'os.environ':276 'os.environ.get':226 'outdat':736 'overview':444 'packag':738 'paddl':637,642 'paddle-webhook':636 'pars':128,317,530 'path':430 'pattern':493,501,562,649 'payload':45,82,129 'payment':572 'post':156,338 'prevent':539 'process':46,344,541 'process.env.elevenlabs':99,122,147,176 'provid':435,558 'python':199,203,304,486 'queue':552,672 'rais':259,292 'rate':678 'raw':110,242 'raw_body.decode':272 'rawbodi':120,160,174 'receiv':4,716 'recommend':59,61,409,489,495 'refer':519 'references/overview.md':445 'references/setup.md':454 'references/verification.md':464 'relat':563 'remov':52,350,357,364,368,375,379 'replac':670 'replay':677 'repositori':594 'request':157,210,240,241,442 'request.body':245 'request.headers.get':165,247,252 'request.text':162 'requir':92,434 'resend':598,603 'resend-webhook':597 'resourc':443 'retri':516,553,559,658,676 'return':182,190,285,315,323,547 'router':481 'save':347 'schedul':560 'sdk':58,66,130,200,301,688,720 'second':531 'secret':77,124,178,279,391,394,462 'see':73,702 'sequenc':511,524,654 'set':11,31 'setup':453 'shopifi':576,581 'shopify-webhook':575 'sig':246,258,275 'sign':461 'signatur':17,37,56,113,134,168,250,255,266,299,307,465 'signaturehead':121,164,175 'skill':30,505,564,689,706,711 'skill-elevenlabs-webhooks' 'source-hookdeck' 'speech':699 'start':423 'status':186,197,261,286,294 'stripe':566,571 'stripe-webhook':565 'test':401 'text':697 'text-to-speech':696 'third':534 'throw':131,322 'timestamp':310 'toler':313 'topic-agent-skills' 'topic-ai-coding' 'topic-api-integrations' 'topic-event-driven' 'topic-github-webhooks' 'topic-llm-tools' 'topic-shopify-webhooks' 'topic-stripe-webhooks' 'topic-webhook-security' 'topic-webhook-signatures' 'topic-webhooks' 'transcript':22,48,340,348,700 'tri':169,268 'trigger':333 'tunnel':425,437 'type':43,282,331,452 'typescript':135 'ui':385,439 'understand':40 'updat':371,384 'use':9,28,62,336,723,729 'user':359,372 'utf':273 'v1.x':737 'valid':308 'variabl':387 'verif':18,38,57,69,201,463,466 'verifi':6,74,305,528 'via':407,417 'voic':51,349,354,361,363,367,374,376,382 'warn':721 'web':438 'webhook':3,8,14,25,34,68,76,81,103,107,123,151,177,232,239,278,390,393,400,448,456,491,499,567,573,577,585,589,595,599,605,609,615,619,625,629,634,638,644,647,667,684,717 'webhook-handler-pattern':490,498,646 'webhook-on':102,150,231 'withdrawn':366","prices":[{"id":"acd1155d-4051-4348-bc7e-aac7c6f324c9","listingId":"bdb43f8d-16d5-4974-9645-8f6fd3703121","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"hookdeck","category":"webhook-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:13:51.518Z"}],"sources":[{"listingId":"bdb43f8d-16d5-4974-9645-8f6fd3703121","source":"github","sourceId":"hookdeck/webhook-skills/elevenlabs-webhooks","sourceUrl":"https://github.com/hookdeck/webhook-skills/tree/main/skills/elevenlabs-webhooks","isPrimary":false,"firstSeenAt":"2026-04-18T22:13:51.518Z","lastSeenAt":"2026-05-02T06:55:46.296Z"}],"details":{"listingId":"bdb43f8d-16d5-4974-9645-8f6fd3703121","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"hookdeck","slug":"elevenlabs-webhooks","github":{"repo":"hookdeck/webhook-skills","stars":69,"topics":["agent-skills","ai-coding","api-integrations","event-driven","github-webhooks","llm-tools","shopify-webhooks","stripe-webhooks","webhook-security","webhook-signatures","webhooks"],"license":"mit","html_url":"https://github.com/hookdeck/webhook-skills","pushed_at":"2026-02-25T14:00:40Z","description":"Webhook integration skills for AI coding agents (Claude Code, Cursor, Copilot). Step-by-step guidance for setting up webhook receivers, signature verification, and event handling for Stripe, Shopify, GitHub, and more. Built on the Agent Skills specification.","skill_md_sha":"2a7e7a335021561ae9a33fe147201dfc37ab70f1","skill_md_path":"skills/elevenlabs-webhooks/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/hookdeck/webhook-skills/tree/main/skills/elevenlabs-webhooks"},"layout":"multi","source":"github","category":"webhook-skills","frontmatter":{"name":"elevenlabs-webhooks","license":"MIT","description":"Receive and verify ElevenLabs webhooks. Use when setting up ElevenLabs webhook handlers, debugging signature verification, or handling call transcription events."},"skills_sh_url":"https://skills.sh/hookdeck/webhook-skills/elevenlabs-webhooks"},"updatedAt":"2026-05-02T06:55:46.296Z"}}