VenddorDocumentação API
API atualAPI legada
Guia rápidoReferência completa
Carregando índice…
API legada/Referência completa/API v2

Webhooks

Cria, lista, lê e remove assinaturas de webhook para receber os eventos da loja no seu sistema.

Um webhook é um endereço seu que a plataforma chama (um POST com JSON) quando algo acontece na loja: um pedido foi criado, um produto mudou, um carrinho foi abandonado. É a forma de manter um ERP, um CRM ou um sistema de logística em dia sem ficar consultando a API de tempos em tempos.

Estas operações gerenciam as assinaturas: qual endereço recebe quais eventos. Os eventos aceitos estão listados no campo events da criação, e a verificação da assinatura de cada envio está descrita mais abaixo, em Como cada envio é assinado.

Na v2 uma assinatura não pode ser alterada. Para mudar o endereço ou os eventos, apague e crie de novo: a nova assinatura recebe um segredo novo.

GET/api/v2/webhooksAdmin

Listar assinaturas

Lista as assinaturas da loja. O segredo vem mascarado (só os 4 últimos caracteres).

Parâmetros de consulta

pageintegerpadrão: 1
Página, a partir de 1.
per_pageintegerpadrão: 20
Itens por página, de 1 a 100.
fieldsstring
Chaves a devolver em cada item, separadas por vírgula.
GET/api/v2/webhooks/{id}Admin

Ler uma assinatura

Devolve uma assinatura, com o segredo mascarado.

Parâmetros de caminho

iduuidobrigatório
Id da assinatura.
POST/api/v2/webhooksAdmin

Criar uma assinatura

Cria a assinatura, já ativa. A resposta traz o segredo completo uma única vez: guarde-o agora, é com ele que você confere a assinatura de cada envio. Nas leituras seguintes o segredo vem mascarado.

Corpo da requisição

urlstringobrigatório
Endereço https (ou http) que vai receber os eventos. Use https. Endereços internos, de loopback ou de rede privada são recusados.
eventsarrayobrigatório
Lista de eventos a receber, no mínimo um. Valores aceitos: order.created, order.statusChanged, order.completed, order.cancelled, order.shipped, product.created, product.updated, product.deleted, customer.registered, customer.updated, cart.abandoned, review.created, vendor.registered, vendor.approved, e os de incentivos incentive.campaign_published, incentive.member_enrolled, incentive.progress_changed, incentive.award_granted, incentive.redemption_updated, incentive.campaign_closed, incentive.resource_changed.
descriptionstring
Nota para identificar a assinatura.
DELETE/api/v2/webhooks/{id}Admin

Remover uma assinatura

Remove a assinatura e o histórico de envios dela. Os eventos deixam de ser enviados na hora.

Parâmetros de caminho

iduuidobrigatório
Id da assinatura.

Exemplo de requisição

bash
curl -X POST "$BASE_URL/api/v2/webhooks" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://erp.minhaempresa.com.br/hooks/venddor",
  "events": [
    "order.created",
    "order.shipped"
  ],
  "description": "Integração com o ERP"
}'

Resposta

201Assinatura criada (segredo completo)
json
{
  "data": {
    "id": "6f4e1b01-bc9a-41cc-8897-ab73c7efe3e5",
    "url": "https://erp.minhaempresa.com.br/hooks/venddor",
    "events": ["order.created", "order.shipped"],
    "secret": "e6f6c80f05ab7f44153d5f0effa269266b4c0732c95174aa20e1014e2512b477",
    "is_active": true,
    "description": "Integração com o ERP",
    "created_at": "2026-10-11T21:10:09.466263068Z",
    "updated_at": "2026-10-11T21:10:09.466263068Z"
  }
}
200Assinatura lida (segredo mascarado)
json
{
  "data": {
    "id": "6f4e1b01-bc9a-41cc-8897-ab73c7efe3e5",
    "url": "https://erp.minhaempresa.com.br/hooks/venddor",
    "events": ["order.created", "order.shipped"],
    "secret": "****b477",
    "is_active": true,
    "description": "Integração com o ERP",
    "created_at": "2026-10-11T21:10:09.466263Z",
    "updated_at": "2026-10-11T21:10:09.466263Z"
  }
}

Campos da resposta

data.iduuid
Id da assinatura.
data.urlstring
Endereço que recebe os eventos.
data.eventsarray
Eventos assinados.
data.secretstring
Segredo usado para assinar cada envio. Completo (64 caracteres hexadecimais) só na criação; depois, **** e os 4 últimos caracteres.
data.is_activeboolean
Se a assinatura está recebendo eventos.
data.descriptionstring
Nota de identificação.
data.created_atstring
Criação (RFC 3339, UTC).
data.updated_atstring
Última alteração (RFC 3339, UTC).

A lista (GET /api/v2/webhooks) devolve data como vetor desses objetos mais meta.pagination. A remoção responde 204 sem corpo.

Erros

StatusQuandoCorpo
400url ausente{"error":{"code":"bad_request","message":"url is required"}}
400Endereço interno ou privado{"error":{"code":"bad_request","message":"webhook url not allowed: ssrf_forbidden: url targets internal/private/loopback address"}}
400events vazio{"error":{"code":"bad_request","message":"at least one event is required"}}
400Evento que não existe{"error":{"code":"bad_request","message":"unsupported event type: foo"}}
404Assinatura inexistente{"error":{"code":"not_found","message":"webhook not found"}}
O segredo não pode ser recuperado

Se você perder o segredo, não há como lê-lo de novo. Apague a assinatura e crie outra. Para trocar o segredo sem perder eventos, crie a nova assinatura primeiro, atualize o seu receptor e só então apague a antiga.

Como cada envio é assinado

Cada envio é um POST com corpo JSON no formato {event, payload, timestamp, webhook_id} e com estes cabeçalhos:

CabeçalhoValor
Content-Typeapplication/json
X-Venddor-Signaturesha256= seguido de 64 caracteres hexadecimais
X-Venddor-EventNome do evento, por exemplo order.created
User-AgentVenddor-Webhook/1.0

Para confirmar que o envio veio da plataforma e não foi alterado, refaça a conta no seu receptor:

  1. Leia o corpo bruto, os bytes exatos que chegaram, antes de qualquer parser de JSON.
  2. Calcule HMAC-SHA256(secret, corpo), usando o secret da assinatura como texto (os 64 caracteres), sem decodificar de hexadecimal.
  3. Escreva o resultado em hexadecimal minúsculo, com o prefixo sha256=, e compare com o cabeçalho usando uma função de tempo constante.
  4. Recuse envios cujo timestamp difira mais de 5 minutos do seu relógio.
js
import crypto from "node:crypto";

function assinaturaValida(rawBody, header, secret) {
  const esperado = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(header || "");
  const b = Buffer.from(esperado);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Responda rápido e confirme a assinatura

O seu receptor deve responder com um status 2xx em até 30 segundos e conferir a assinatura de cada envio antes de confiar no conteúdo.

Veja também

  • Visão geral da API v2
Anterior
Sellers
Próxima
App do seller (1.0)
Nesta página
  • Exemplo de requisição
  • Resposta
  • Erros
  • Como cada envio é assinado
  • Veja também