Skip to content

Webhooks

Receba notificações em tempo real quando eventos acontecem na loja. A Vitry envia requisições HTTP POST para URLs que você registra.

Como funciona

  1. Você registra uma URL e escolhe quais eventos quer ouvir
  2. Quando um evento ocorre, a Vitry envia um POST com os dados
  3. Você valida a assinatura e processa os dados

Eventos disponíveis

EventoDescrição
order.createdPedido criado
order.paidPagamento confirmado
order.cancelledPedido cancelado
order.shippedPedido enviado
product.createdProduto criado
product.updatedProduto atualizado
product.deletedProduto excluído
customer.createdCliente cadastrado

Listar webhooks

http
GET /api/v1/webhooks

Resposta

json
{
  "data": [
    {
      "id": 1,
      "url": "https://meuservidor.com/webhook",
      "events": ["order.created", "order.paid"],
      "is_active": true,
      "last_triggered_at": "2026-03-15T10:30:00Z",
      "failure_count": 0,
      "created_at": "2026-03-01T08:00:00Z",
      "updated_at": "2026-03-15T10:30:00Z"
    }
  ]
}

Registrar webhook

http
POST /api/v1/webhooks

Campos

CampoTipoObrigatórioDescrição
urlstringURL que receberá os POST (HTTPS recomendado)
eventsarrayLista de eventos para ouvir

Exemplo

bash
curl -X POST https://sualoja.com.br/api/v1/webhooks \
  -H "X-API-Key: SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://meuservidor.com/webhook/vitry",
    "events": ["order.created", "order.paid", "product.updated"]
  }'

Resposta 201 Created

json
{
  "data": {
    "id": 1,
    "url": "https://meuservidor.com/webhook/vitry",
    "events": ["order.created", "order.paid", "product.updated"],
    "is_active": true,
    "failure_count": 0,
    "created_at": "2026-03-17T12:00:00Z"
  },
  "secret": "a1b2c3d4e5f6...seu_secret_aqui",
  "message": "Webhook criado. Guarde o secret — ele não será exibido novamente."
}

IMPORTANTE

O secret é retornado apenas uma vez nesta resposta. Copie e armazene em local seguro. Ele é usado para verificar a autenticidade das notificações.

Remover webhook

http
DELETE /api/v1/webhooks/{id}

Resposta

json
{
  "message": "Webhook removido."
}

Formato das notificações

Quando um evento ocorre, a Vitry envia um POST para sua URL com o seguinte formato:

Headers

HeaderDescrição
Content-Typeapplication/json
User-AgentVitry-Webhook/1.0
X-Vitry-EventNome do evento (ex: order.created)
X-Vitry-DeliveryUUID único desta entrega
X-Vitry-SignatureAssinatura HMAC-SHA256 do body

Body

json
{
  "event": "order.created",
  "data": {
    "id": 42,
    "order_number": "2026-00042",
    "customer": { "id": 5, "name": "João Silva" },
    "status": "pending",
    "total": 124.70
  },
  "timestamp": "2026-03-15T10:25:00Z"
}

O campo data contém o recurso completo no mesmo formato da API REST (ex: OrderResource, ProductResource, etc.).


Verificando a assinatura

Para garantir que a notificação veio da Vitry, verifique a assinatura HMAC-SHA256.

php
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_VITRY_SIGNATURE'] ?? '';

$expected = hash_hmac('sha256', $payload, $webhookSecret);

if (! hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Assinatura inválida');
}

$data = json_decode($payload, true);
// Processar evento...
javascript
const crypto = require('crypto');

app.post('/webhook/vitry', (req, res) => {
  const payload = JSON.stringify(req.body);
  const signature = req.headers['x-vitry-signature'];

  const expected = crypto
    .createHmac('sha256', webhookSecret)
    .update(payload)
    .digest('hex');

  if (signature !== expected) {
    return res.status(401).send('Assinatura inválida');
  }

  const { event, data } = req.body;
  // Processar evento...

  res.status(200).send('OK');
});
python
import hmac
import hashlib

@app.route('/webhook/vitry', methods=['POST'])
def handle_webhook():
    payload = request.get_data()
    signature = request.headers.get('X-Vitry-Signature', '')

    expected = hmac.new(
        webhook_secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(expected, signature):
        return 'Assinatura inválida', 401

    data = request.get_json()
    # Processar evento...

    return 'OK', 200

Retentativas

Se sua URL retornar um status diferente de 2xx, a Vitry faz retentativas:

TentativaIntervalo
Imediata
10 segundos
60 segundos (1 min)
  • Timeout: 10 segundos por requisição
  • Desativação automática: Após 5 falhas consecutivas, o webhook é desativado automaticamente
  • Webhooks desativados podem ser reativados removendo e criando novamente

Boas práticas

  • Responda rápido: Retorne 200 OK imediatamente e processe os dados de forma assíncrona
  • Verifique a assinatura: Sempre valide o header X-Vitry-Signature
  • Use HTTPS: Proteja os dados em trânsito
  • Idempotência: Use o header X-Vitry-Delivery para evitar processar a mesma notificação duas vezes
  • Logs: Armazene os payloads recebidos para debugging