SociaHive Docs

Webhooks

Receba eventos assinados do SociaHive no seu próprio endpoint HTTPS e verifique a assinatura.

Um webhook envia um POST HTTPS para o seu endpoint quando algo acontece na sua conta do SociaHive: um post agendado é publicado ou falha, uma automação começa para alguém ou encontra um erro, um modelo do WhatsApp é aprovado ou rejeitado.

Adicione um no painel, em Integrações → Webhooks, ou pela API REST (/api/v1/webhooks, escopos webhooks:read e webhooks:write).

Qualquer pessoa pode configurar um webhook, mas os eventos só são entregues enquanto o seu plano inclui acesso à API (o teste grátis e todos os planos pagos). Os webhooks que você criou continuam lá e voltam a enviar quando você faz upgrade.

Limites por plano

PlanoWebhooks
Free0
Creator2
Studio5
Pro10
Agency50

O limite vale para integration_type webhook, custom e n8n. As assinaturas do Zapier e do Make (zapier, make) não contam.

Eventos

EventoQuandoCampos de data
post.publishedUm post agendado foi ao ar em uma plataformapostId, platform, accountId, platformPostId
post.failedUm post agendado não pôde ser publicado em uma plataformapostId, platform, accountId, error
flow.triggeredUma automação começou para alguémflowId, executionId, platform, accountId, senderId
flow.errorUma automação parou com um erroflowId, executionId (quando conhecido), flowName, errorMessage, errorNodeId
whatsapp.template_statusA Meta aprovou, rejeitou ou pausou um modelo do WhatsAppaccountId, templateName, templateLanguage, event, reason
post.review_decisionUm cliente aprovou um post, pediu mudanças ou deixou um comentário em um link de revisãopostId, reviewLinkId, kind (approved, changes_requested, comment), reviewerName, comment (quando houver)
post.plug_firedUm plug de um post disparou (um repost ou um comentário)plug_id, post_id, account_id, platform, metric, threshold, value, action

Um post publicado em três plataformas envia três eventos post.published, um por plataforma.

O post.review_decision exige os links de revisão para clientes (Studio, Pro e Agency) e o post.plug_fired exige os plugs (todos os planos pagos). Assinar um evento que o seu plano não inclui devolve 400.

O contato nos eventos sobre uma pessoa

flow.triggered, flow.error (quando indica a pessoa), os eventos de assinantes da newsletter e data.collected também trazem contact, a pessoa como o SociaHive a conhece no momento do envio do evento:

"contact": {
  "id": "6733a1b2c3d4e5f601234567",
  "name": "Jamie Rivera",
  "email": "[email protected]",
  "phone": "+15555550123",
  "status": "active",
  "tags": ["lead", "webinar"],
  "custom_fields": { "Company": "Rivera Studio", "Plan interest": "Pro" },
  "platform_identities": [{ "platform": "instagram", "platform_user_id": "1784140000000000", "username": "jamie.rivera" }]
}

Os campos personalizados usam como chave os nomes que você vê no SociaHive. contact não é enviado quando o SociaHive ainda não tem um contato para a pessoa.

Aceitos, mas ainda não enviados

Você pode assinar estes eventos pela API (o app do Make e o nó do n8n os oferecem), mas o SociaHive ainda não os envia. Um webhook inscrito nesses eventos passa a recebê-los quando forem lançados, sem nenhuma mudança do seu lado.

EventoSignificado previsto
message.receivedAlguém enviou um direct para uma das suas contas
comment.receivedAlguém comentou em um dos seus posts
flow.completedUma automação terminou para alguém
account.disconnectedUma conta conectada foi desconectada

O painel só oferece os eventos que são enviados hoje.

Limitar um webhook a algumas contas

Defina account_ids (IDs das contas conectadas, de GET /api/v1/connected-accounts) para receber só os eventos dessas contas. Deixe vazio para todas as contas. Os eventos informam a conta como accountId (post.plug_fired: account_id). Os eventos que não informam conta (flow.error, post.review_decision) sempre são enviados.

Formato da requisição

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"
  }
}

Responda com qualquer status 2xx em até 10 segundos. Deixe o trabalho demorado para depois de responder.

Verificar a assinatura

Toda requisição é assinada com o segredo de assinatura do webhook, que aparece uma vez ao criar o webhook (e de novo apenas quando você gera um novo segredo).

O X-SociaHive-Signature tem o formato t=<segundos unix>,v1=<hex>. O v1 é o HMAC-SHA256 do texto <t>.<corpo bruto da requisição>, com o seu segredo como chave.

  1. Leia o corpo bruto antes de qualquer leitura de JSON: serializar de novo muda os bytes.
  2. Calcule o HMAC e compare com o v1 em tempo constante.
  3. Rejeite a requisição se o t estiver a mais de cinco minutos de agora. Isso impede ataques de repetição (replay).
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)

Entrega e novas tentativas

  • A entrega é pelo menos uma vez. O mesmo evento pode chegar mais de uma vez; use o id (também em X-SociaHive-Event-Id) para ignorar duplicatas.
  • Uma entrega que falha (resposta que não seja 2xx, tempo esgotado ou falta de conexão) é tentada até 5 vezes no total, com intervalos cada vez maiores entre as tentativas.
  • Depois de 3 eventos seguidos que falham em todas as tentativas, o webhook é desligado e você recebe uma notificação no app. Corrija o endpoint e ligue o webhook de novo; a contagem de falhas recomeça do zero.
  • Não há garantia de que os eventos cheguem em ordem. Use o timestamp se a ordem importar.
  • Os endpoints precisam ser URLs https públicas. Endereços privados e internos são recusados.

Testes

O botão Enviar teste no painel envia na hora um evento assinado e mostra o código de status e o tempo:

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

Funciona em um webhook desligado, então você pode testar um endpoint antes de ligá-lo de novo. Dá para enviar 5 testes por minuto.

API REST

MétodoCaminhoO que faz
GET/api/v1/webhooksLista seus webhooks, inclusive os desligados
POST/api/v1/webhooksCria um: target_url, events, e opcionalmente integration_type (webhook por padrão, custom, n8n, make, zapier) e account_ids. A resposta inclui signing_secret
PATCH/api/v1/webhooks/{id}Altera target_url, events, account_ids ou active (true liga de novo e zera a contagem de falhas)
DELETE/api/v1/webhooks/{id}Exclui. Depois você pode adicionar a mesma URL de novo

Cada webhook em uma resposta traz last_delivery_at, last_status (o status HTTP, ou null quando o endpoint não respondeu) e last_error.

On this page