SociaHive Docs

Webhooks

Receive signed events from SociaHive at your own HTTPS endpoint, and verify them.

A webhook sends an HTTPS POST to your endpoint when something happens in your SociaHive account: a scheduled post is published or fails, an automation starts for someone or hits an error, a WhatsApp template is approved or rejected.

Add one in the dashboard under Integrations → Webhooks, or with the REST API (/api/v1/webhooks, scopes webhooks:read and webhooks:write).

Anyone can set up a webhook, but events are only delivered while your plan includes API access (the free trial and every paid plan). Webhooks you created stay in place and start sending again when you upgrade.

Plan limits

PlanWebhooks
Free0
Creator2
Studio5
Pro10
Agency50

The limit covers integration_type webhook, custom and n8n. Zapier and Make subscriptions (zapier, make) do not count toward it.

Events

EventWhendata fields
post.publishedA scheduled post went live on one platformpostId, platform, accountId, platformPostId
post.failedA scheduled post could not be published on one platformpostId, platform, accountId, error
flow.triggeredAn automation started for someoneflowId, executionId, platform, accountId, senderId
flow.errorAn automation stopped with an errorflowId, executionId (when known), flowName, errorMessage, errorNodeId
whatsapp.template_statusMeta approved, rejected or paused a WhatsApp templateaccountId, templateName, templateLanguage, event, reason
post.review_decisionA client approved a post, asked for changes or left a comment on a review linkpostId, reviewLinkId, kind (approved, changes_requested, comment), reviewerName, comment (when given)
post.plug_firedA plug on a post fired (a repost or a comment)plug_id, post_id, account_id, platform, metric, threshold, value, action

A post published to three platforms sends three post.published events, one per platform.

post.review_decision needs client review links (Studio, Pro and Agency) and post.plug_fired needs plugs (every paid plan). Subscribing to one your plan does not include answers 400.

Accepted, not sent yet

You can subscribe to these through the API (the Make app and the n8n node offer them), but SociaHive does not send them yet. A webhook subscribed to them receives them once they ship, with no change on your side.

EventPlanned meaning
message.receivedSomeone sent one of your accounts a direct message
comment.receivedSomeone commented on one of your posts
flow.completedAn automation finished for someone
account.disconnectedA connected account was disconnected

The dashboard only offers events that are sent today.

Limiting a webhook to some accounts

Set account_ids (connected account ids, from GET /api/v1/connected-accounts) to receive only events about those accounts. Leave it empty for every account. Events name their account as accountId (post.plug_fired: account_id). Events that do not name an account (flow.error, post.review_decision) are always sent.

Request format

POST /your/endpoint HTTP/1.1
Content-Type: application/json
X-SociaHive-Event: post.published
X-SociaHive-Event-Id: evt_0199a3c4f2b8c1d2e3f4a5b6
X-SociaHive-Timestamp: 1791532800
X-SociaHive-Signature: t=1791532800,v1=5f2b0c9d...
{
  "id": "evt_0199a3c4f2b8c1d2e3f4a5b6",
  "event": "post.published",
  "timestamp": "2026-10-09T12:00:00.000Z",
  "data": {
    "postId": "66f0c2a1b2c3d4e5f6a7b8c9",
    "platform": "instagram",
    "accountId": "66e1a2b3c4d5e6f7a8b9c0d1",
    "platformPostId": "17912345678901234"
  }
}

Answer with any 2xx status within 10 seconds. Do slow work after you answer.

Verifying the signature

Every request is signed with the webhook's signing secret, which is shown once when you create the webhook (and again only when you rotate it).

X-SociaHive-Signature has the form t=<unix seconds>,v1=<hex>. v1 is the HMAC-SHA256 of the string <t>.<raw request body>, keyed with your secret.

  1. Read the raw body before any JSON parsing; re-serialising changes the bytes.
  2. Compute the HMAC and compare it to v1 in constant time.
  3. Reject the request if t is more than five minutes from now. This stops replays.
import crypto from 'node:crypto'
import express from 'express'
 
const app = express()
const SECRET = process.env.SOCIAHIVE_WEBHOOK_SECRET
const TOLERANCE_SEC = 300
 
function verify(rawBody, header) {
  const parts = Object.fromEntries(
    (header ?? '').split(',').map((p) => p.split('=', 2)),
  )
  const t = Number(parts.t)
  if (!parts.v1 || !Number.isFinite(t)) return false
  if (Math.abs(Date.now() / 1000 - t) > TOLERANCE_SEC) return false
 
  const expected = crypto
    .createHmac('sha256', SECRET)
    .update(`${t}.${rawBody}`)
    .digest('hex')
  const a = Buffer.from(expected, 'hex')
  const b = Buffer.from(parts.v1, 'hex')
  return a.length === b.length && crypto.timingSafeEqual(a, b)
}
 
app.post('/sociahive-webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const rawBody = req.body.toString('utf8')
  if (!verify(rawBody, req.get('X-SociaHive-Signature'))) {
    return res.status(400).send('bad signature')
  }
  const event = JSON.parse(rawBody)
  res.sendStatus(200)
  // Handle event.event / event.data here, after answering.
})
 
app.listen(3000)

Delivery and retries

  • Delivery is at least once. The same event can arrive more than once; use id (also in X-SociaHive-Event-Id) to skip duplicates.
  • A failed delivery (a non-2xx answer, a timeout, or no connection) is tried up to 5 times in all, with growing delays between tries.
  • After 3 events in a row fail every retry, the webhook is switched off and you get an in-app notification. Fix the endpoint, then switch it back on; the failure count starts again from zero.
  • Events are not guaranteed to arrive in order. Use timestamp if order matters.
  • Endpoints must be public https URLs. Private and internal addresses are refused.

Testing

Send test in the dashboard posts one signed event right away and shows the status code and time:

{
  "id": "evt_...",
  "event": "test",
  "timestamp": "2026-10-09T12:00:00.000Z",
  "data": { "webhook_id": "66f0...", "message": "This is a test event from SociaHive." }
}

It works on a webhook that is switched off, so you can check an endpoint before switching it back on. You can send 5 tests a minute.

REST API

MethodPathWhat it does
GET/api/v1/webhooksList your webhooks, including ones that are off
POST/api/v1/webhooksCreate one: target_url, events, optional integration_type (webhook default, custom, n8n, make, zapier) and account_ids. The response includes signing_secret
PATCH/api/v1/webhooks/{id}Change target_url, events, account_ids, or active (true switches it back on and resets the failure count)
DELETE/api/v1/webhooks/{id}Delete it. You can add the same URL again afterwards

Each webhook in a response carries last_delivery_at, last_status (the HTTP status, or null when the endpoint did not answer) and last_error.

On this page