We use PostHog analytics cookies on this marketing site to understand how visitors use sparkvox.io - only if you accept. The app at app.sparkvox.io does not use marketing analytics. Cookie Policy.

Webhooks

Register endpoints and verify signed event delivery.

GET/api/v1/webhooks

List Webhooks

List registered webhooks (secrets are not returned).

Response 200

json
{
  "webhooks": [
    {
      "id": "uuid",
      "url": "https://example.com/webhook",
      "events": ["project.ready"],
      "created_at": "..."
    }
  ]
}
POST/api/v1/webhooks

Register Webhook

Register a webhook URL to receive signed event notifications.

Request body

json
{
  "url": "https://example.com/webhook",
  "events": ["project.ready", "project.failed"]
}

Response 201

json
{
  "id": "uuid",
  "url": "https://example.com/webhook",
  "events": ["project.ready", "project.failed"],
  "secret": "abc123...",
  "created_at": "..."
}

Store the secret now - it is shown only once. Use it to verify X-SparkVox-Signature on incoming requests.

DELETE/api/v1/webhooks/:id

Delete Webhook

Remove a webhook. Returns 200 with { "deleted": true }.

Webhook Events

SparkVox sends a signed POST to your endpoint when events occur.

Request format

http
POST https://example.com/webhook
Content-Type: application/json
X-SparkVox-Signature: <hmac-sha256-hex>
X-SparkVox-Event: project.ready

Signature verification

javascript
const crypto = require("crypto");

function verifySignature(body, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(body, "utf8")
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

project.ready

Fired when all posts have been generated for a project.

json
{
  "event": "project.ready",
  "data": {
    "project_id": "uuid",
    "title": "My Episode",
    "post_count": 12,
    "posts_url": "https://app.sparkvox.io/api/v1/projects/<id>/posts"
  },
  "timestamp": 1748790000000
}

project.failed

Fired when a project fails at any pipeline stage (ingest, transcription, billing, generation). Processing time is refunded automatically when a charged project fails.

json
{
  "event": "project.failed",
  "data": {
    "project_id": "uuid",
    "error": "insufficient_credits"
  },
  "timestamp": 1748790000000
}

data.error may be insufficient_credits (not enough processing time), billing_error, or a truncated pipeline error message (max 500 characters).

v1 delivery: Fire-and-forget. No automatic retry. If your endpoint returns a non-2xx status the event is dropped.