Skip to content
Playcut Docs

Webhooks

Configure a webhook URL on your API key to receive a signed HTTP POST when tasks complete or fail.

Pass webhookUrl when creating an API key:

Terminal window
curl -X POST https://api.playcut.ai/api/v1/api-keys \
-H "Authorization: Bearer $CLERK_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"label": "Production",
"webhookUrl": "https://your-app.com/webhooks/playcut"
}'

The response includes a one-time webhookSecret. Store it securely.

{
"key": "pk_live_...",
"webhookSecret": "a3f8c2d1...",
"apiKey": { ... }
}
{
"id": "whev_64f3a1b2c3d4e5f6",
"type": "task.completed",
"createdAt": "2026-05-18T12:00:00.000Z",
"data": {
"taskId": "abc123",
"taskType": "GEMINI_TEXT_TO_IMAGE",
"status": "COMPLETED",
"output": { "assetIds": ["asset_xyz"] }
}
}

For failed tasks the type is task.failed and data includes an error object.

Every request includes X-Playcut-Signature: sha256=<hex>. Verify it before processing:

import { createHmac } from "crypto"
import express from "express"
app.post("/webhooks/playcut", express.raw({ type: "application/json" }), (req, res) => {
const sig = req.headers["x-playcut-signature"] as string
const expected = "sha256=" + createHmac("sha256", process.env.PLAYCUT_WEBHOOK_SECRET!)
.update(req.body)
.digest("hex")
if (expected !== sig) return res.status(401).send("Invalid signature")
const event = JSON.parse(req.body.toString())
// handle event...
res.json({ ok: true })
})
AttemptDelay
1Immediate
260 seconds
35 minutes

After 3 failed attempts the delivery is permanently marked as failed.

Send a synthetic event to verify your endpoint:

Terminal window
curl -X POST https://api.playcut.ai/api/v1/api-keys/{keyId}/webhook/test \
-H "Authorization: Bearer $CLERK_SESSION_TOKEN"
{ "delivered": true, "httpStatus": 200 }