# Webhooks [View original](https://ittybit.com/docs/webhooks) ## Why Use Webhooks? By default, applications can check task or automation status using the API or SDK. However, polling frequently may lead to unnecessary API requests. Using webhooks allows your app to: * React automatically when a task completes. * Update your database or trigger further processing. * Send alerts or moderation actions when results (like NSFW detection) arrive. *** ## Webhook Delivery When a task or automation step completes, Ittybit sends an HTTPS `POST` request to your configured `webhook_url` with JSON describing the event and its results. ```json { "id": "task_123abc", "object": "task", "kind": "nsfw", "status": "completed", "results": { "is_nsfw": true, "confidence": 0.97 }, "project_id": "proj_xyz", "automation_id": "auto_456def", "created": "2025-01-10T12:34:56Z", "completed": "2025-01-10T12:35:22Z" } ``` *** ## Configuring Webhooks in Automations You can add webhook actions in your automations directly or define a webhook URL per task. ### Example — Add a webhook in an automation ```js const automation = await ittybit.automations.create({ name: "Notify app when media is ready", trigger: { kind: "event", event: "media.created" }, workflow: [ { kind: "webhook", url: "https://your-app.com/ittybit-webhook", ref: "notify-server" } ] }); ``` When a new media object is created in your project, Ittybit will POST a JSON payload to your webhook URL. ### Example — Set a webhook per task ```js const task = await ittybit.tasks.create({ kind: "nsfw", url: imageUrl, webhook_url: "https://your-app.com/nsfw-webhook" }); ``` Once the task finishes processing, the webhook endpoint receives the task’s results. *** ## Handling Webhooks in Your App Your server should expose an endpoint that listens for `POST` requests. For example, using Express.js: ```js app.post("/ittybit-webhook", async (req, res) => { const { id, status, results } = req.body || {}; if (status !== "completed") { return res.status(200).send("Task not completed yet"); } // Example: update database await db.tasks.update({ where: { task_id: id }, data: { status, results }, }); res.status(200).send("Webhook processed successfully"); }); ``` Always return a `200 OK` within 5 seconds to confirm delivery. *** ## Verified Event Triggers Currently documented and supported events: | Event | Description | | -------------- | -------------------------------------------------------------------------------------------- | | media.created | Triggered when a new media object is created in your project. | | task.completed | Triggered when a task finishes processing (for example, NSFW detection or video conversion). | > More event types will be documented in the [Events](/docs/automations/events) section as they become publicly available. *** ## Security Each webhook request is signed by Ittybit. The header format is: ``` Ittybit-Signature: t=,v1= ``` You can validate this signature using your API key before trusting the payload. > Signature verification documentation is being finalized and will be added soon. *** ## Example — Supabase Integration Webhooks are used throughout Ittybit’s Supabase guides to sync results automatically. For example, in [Check every Supabase upload for NSFW content](/guides/check-for-nsfw-content), a webhook updates the database when Ittybit finishes detection: ```js app.post("/nsfw-webhook", async (req, res) => { const { id, results } = req.body; await supabase .from("uploads") .update({ nsfw_detected: results?.is_nsfw || false, nsfw_confidence: results?.confidence || 0 }) .eq("task_id", id); res.status(200).send("Updated NSFW status"); }); ``` *** ## Best Practices * Use HTTPS — HTTP URLs will be rejected. * Return a 200 response quickly. * Log all incoming payloads for debugging. * Use unique webhook URLs per automation if possible. * If your endpoint fails, Ittybit retries automatically with exponential backoff. *** ## Summary Webhooks let you integrate Ittybit’s automations directly into your own workflows. They notify your app instantly when media or tasks complete, removing the need for polling and allowing fully event-driven automation.