Agent skill

Argil Webhooks Skill

Receive and verify Argil (argil.ai) AI avatar video webhooks, signed per Standard Webhooks. Use when setting up an Argil webhook endpoint, getting the whsec_ signing secret from POST /webhooks, debugging webhook-id / webhook-timestamp / webhook-signature verification, or handling VIDEO_GENERATION_SUCCESS, VIDEO_GENERATION_FAILED, AVATAR_TRAINING_SUCCESS and AVATAR_TRAINING_FAILED events.

Install this skill

npx skills add hookdeck/webhook-skills --skill argil-webhooks


Argil is an AI avatar video generation platform. Its webhooks report video renders and avatar trainings finishing or failing. Deliveries are signed per Standard Webhooks with webhook-id, webhook-timestamp and webhook-signature headers.

When to Use This Skill

  • How do I receive Argil webhooks?
  • How do I verify an Argil webhook signature?
  • Where do I get my Argil webhook signing secret?
  • How do I handle VIDEO_GENERATION_SUCCESS or AVATAR_TRAINING_FAILED?
  • Why is my Argil webhook-signature verification failing, or why are there no signature headers?
  • How do I dedupe Argil webhook retries?

Signing requirement: recreate old webhooks

Webhooks created before Argil added signing are delivered unsigned, and there is no way to retrieve a secret for them. Recreate the webhook to get a whsec_ secret (Hookdeck's alert for this source says the same: "Webhooks created before Argil added signing are unsigned. Recreate the webhook to get a whsec_ secret."). The secret is returned once, in the response of POST /webhooks, so store it then.

Verification (core)

HeaderValue
webhook-idThe event ID, the same on every retry
webhook-timestampUnix seconds when this attempt was sent
webhook-signaturev1,<base64 HMAC-SHA256>, possibly several space-separated entries

Signed content is {webhook-id}.{webhook-timestamp}.{raw body}. The key is the base64-decoded part of the secret after whsec_. Argil's docs show the standardwebhooks library (npm, PyPI). It enforces a fixed 5-minute timestamp window and compares in constant time. If webhook-id is missing, read the svix-* headers instead: same scheme, other prefix.

const { Webhook } = require('standardwebhooks');

// rawBody: exact request body string, NOT re-serialised JSON
function verifyArgilWebhook(rawBody, get, secret = process.env.ARGIL_WEBHOOK_SECRET) {
  const prefix = get('webhook-id') ? 'webhook' : 'svix';
  return new Webhook(secret).verify(rawBody, {
    'webhook-id': get(`${prefix}-id`),
    'webhook-timestamp': get(`${prefix}-timestamp`),
    'webhook-signature': get(`${prefix}-signature`),
  }); // returns the parsed { event, data }; throws → respond 400
}

Python: from standardwebhooks.webhooks import Webhook, then Webhook(secret).verify(await request.body(), {...same mapping...}).

Late retries. Hookdeck retries and replays resend the original timestamp, so the library rejects them after 5 minutes. A dependency-free manual verifier with no window is in references/verification.md.

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Event Envelope

{ "event": "VIDEO_GENERATION_SUCCESS",
  "data": { "videoId": "...", "videoName": "...", "videoUrl": "https://...",
            "message": "Video generation completed successfully",
            "extras": "...", "renderCost": 150, "renderCostRefunded": false } }

The event name is the top-level event string. The payload has no event ID: dedupe on the webhook-id header.

Common Event Types

EventFired whendata fields
VIDEO_GENERATION_SUCCESSA video render succeedsvideoId, videoName, videoUrl, message, extras, renderCost, renderCostRefunded (false)
VIDEO_GENERATION_FAILEDA video render failsvideoId, videoName, message (why), extras, renderCost, renderCostRefunded
AVATAR_TRAINING_SUCCESSAn avatar training succeedsavatarId, voiceId, avatarName, extras
AVATAR_TRAINING_FAILEDAn avatar training failsavatarId, avatarName, extras

Argil's Avatar Training Failed page calls the event AVATAR_GENERATION_FAILED in its prose, but its payload example and the subscription enum use AVATAR_TRAINING_FAILED. Use that.

Full payloads: references/overview.md and Argil's webhook docs.

Delivery Semantics

  • Return a 2xx within 10 seconds, then process asynchronously. Redirects are not followed.
  • Failed deliveries retry after 30 s, 2 min, 10 min, 1 h, 6 h, then every 12 h for 3 days.
  • Delivery is at least once and can arrive out of order.
  • Answer 410 Gone to disable the webhook. Three days of failures disables it too and emails the workspace owner. Updating a disabled webhook enables it again.

Environment Variables

ARGIL_WEBHOOK_SECRET=whsec_xxxxx   # full value incl. whsec_; handlers fail closed (500) without it

Local Development

# Express / Next.js (use 8000 for FastAPI). No install or account required.
npx hookdeck-cli listen 3000 argil --path /webhooks/argil

Create a webhook with the printed URL as callbackUrl (see references/setup.md), then render a video or train an avatar.

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 13, 2026

View on GitHub →