Skip to content

How to set up and verify webhooks ​

Create an endpoint with POST /api/webhooks, subscribe it to the events you need, and verify the X-Webhook-Signature header on every delivery. Socifyr then calls your URL when a post finishes or a single platform succeeds or fails, so you stop polling.

Webhooks are a Business plan feature. See limits for the endpoint cap. On other plans, creating a webhook returns Webhooks are not available on your current plan. Upgrade to Business to continue.

How do I create a webhook? ​

text
The dashboard has no webhook screen. Create and manage webhooks with the
REST API or the TypeScript SDK.
text
The CLI has no webhook commands.
typescript
const hook = await socifyr.webhooks.create({
  url: 'https://myapp.com/webhooks/socifyr',
  events: ['upload.completed', 'upload.partial_failure', 'platform.failed'],
  description: 'Content pipeline',
})
console.log(hook.id, hook.secret) // the secret is shown once: store it now
text
No webhook management in the Python SDK. Create the endpoint with REST or the
TypeScript SDK. Python can verify signatures: see below.
bash
curl -X POST https://api.socifyr.com/api/webhooks \
  -H "Authorization: Bearer $SOCIFYR_API_KEY" \
  -H "X-Workspace-Id: $SOCIFYR_WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://myapp.com/webhooks/socifyr",
    "events": ["upload.completed", "upload.partial_failure", "platform.failed"],
    "description": "Content pipeline"
  }'
text
No webhook tools. The MCP server cannot create or read webhooks, and a key
with guardrails cannot call the webhook routes at all.

Response (secret shown once, masked on later reads):

json
{
  "success": true,
  "data": {
    "id": "6a05300000000000000000cc",
    "url": "https://myapp.com/webhooks/socifyr",
    "secret": "9f2c...64 hex characters...",
    "events": ["upload.completed", "upload.partial_failure", "platform.failed"],
    "active": true,
    "description": "Content pipeline",
    "createdAt": "2026-11-13T09:00:00.000Z",
    "updatedAt": "2026-11-13T09:00:00.000Z"
  }
}

The five events are upload.completed, upload.failed, upload.partial_failure, platform.success and platform.failed. Payloads for each are in webhook payloads.

How do I verify the signature? ​

Socifyr signs the raw request body with HMAC-SHA256 using your webhook secret and sends X-Webhook-Signature: sha256=<hex>. Compare against the raw bytes, not a re-serialized object.

typescript
import express from 'express'
import { verifyWebhookSignature, parseWebhookEvent } from '@socifyr/sdk'

const app = express()

app.post('/webhooks/socifyr', express.raw({ type: 'application/json' }), (req, res) => {
  const ok = verifyWebhookSignature(
    req.body,
    req.headers['x-webhook-signature'] as string,
    process.env.SOCIFYR_WEBHOOK_SECRET!,
  )
  if (!ok) return res.status(401).send('Invalid signature')

  const event = parseWebhookEvent(req.body)
  if (event.event === 'platform.failed') {
    console.warn('Failed on', event.payload)
  }
  res.sendStatus(200)
})
python
import os
from flask import Flask, request, abort
from socifyr import verify_webhook_signature

app = Flask(__name__)

@app.post("/webhooks/socifyr")
def hook():
    ok = verify_webhook_signature(
        request.get_data(),                      # raw bytes
        request.headers.get("X-Webhook-Signature", ""),
        os.environ["SOCIFYR_WEBHOOK_SECRET"],
    )
    if not ok:
        abort(401)
    event = request.get_json()
    return "", 200

More languages and the manual HMAC code are in Verifying signatures.

How do I check that deliveries are arriving? ​

bash
curl https://api.socifyr.com/api/webhooks/6a05300000000000000000cc/deliveries \
  -H "Authorization: Bearer $SOCIFYR_API_KEY"
typescript
const deliveries = await socifyr.webhooks.deliveries('6a05300000000000000000cc')

You get the last 50 attempts with status, statusCode and attempts. Failed deliveries retry up to 5 times with exponential backoff starting at 10 seconds. Respond with a 2xx quickly and do heavy work after.

How do I pause or delete a webhook? ​

typescript
await socifyr.webhooks.update('6a05300000000000000000cc', { active: false })
await socifyr.webhooks.delete('6a05300000000000000000cc')

REST: PATCH /api/webhooks/:id with { "active": false }, and DELETE /api/webhooks/:id.

What errors can I get, and how do I fix them? ​

ErrorStatusFix
Webhooks are not available on your current plan. Upgrade to Business to continue.403Upgrade, or poll status.
Maximum of N webhook endpoints allowed on your plan400Delete an endpoint first.
Validation error on url400Use an http or https URL with a top-level domain.
This API key has guardrails and cannot call this endpoint ...403Use a session or an unrestricted key.
Your handler returns 401 for every deliveryn/aYou verified against a parsed body. Use the raw body and the right secret.

FAQ ​

Can I choose the signing secret? ​

No. The server generates it. To rotate, delete the endpoint and create a new one.

Why does one post send several events? ​

platform.success and platform.failed fire per account as each finishes. The upload.* events fire once when the whole post ends. Subscribe only to what you handle.

Next steps ​