Skip to main content
O Triglit envia webhooks para seus endpoints quando eventos importantes ocorrem durante a execução de workflows, como conclusão, falhas ou pausas. Os webhooks são entregues através do Svix, uma plataforma confiável de entrega de webhooks.

O que são Webhooks?

Webhooks são notificações HTTP enviadas pelo Triglit para seus endpoints quando eventos ocorrem. Isso permite que você reaja a eventos em tempo real sem precisar fazer polling constante.

Eventos Disponíveis

O Triglit envia os seguintes eventos de execução de workflows:
  • run.started: Execução (run) iniciada
  • run.completed: Execução concluída com sucesso
  • run.failed: Execução falhou
  • run.cancelled: Execução cancelada
  • run.paused: Execução pausada (aguardando retomada)
  • run.resumed: Execução retomada após pausa

Configuração

1. Configurar Webhook no Frontend

A configuração de webhooks é feita através do painel do Triglit (frontend), não via API. No painel, você pode:
  1. Acessar as configurações de webhooks
  2. Adicionar um endpoint para receber notificações
  3. Selecionar quais eventos deseja receber
  4. Ver o secret para validação
A configuração de webhooks é feita apenas pelo frontend do Triglit. Não há endpoints de API para cadastro de webhooks.

2. Implementar Endpoint

Como os webhooks são entregues via Svix, você precisa validar a assinatura usando o SDK do Svix ou validar manualmente:
const svix = require('svix');

const webhook = new svix.Webhook(process.env.SVIX_SECRET);

app.post('/webhooks/triglit', express.raw({ type: 'application/json' }), (req, res) => {
  try {
    // Validar assinatura usando Svix
    const payload = webhook.verify(req.body, {
      'svix-id': req.headers['svix-id'],
      'svix-timestamp': req.headers['svix-timestamp'],
      'svix-signature': req.headers['svix-signature']
    });
    
    const event = JSON.parse(payload);
    
    switch (event.type) {
      case 'run.completed':
        handleRunCompleted(event.data);
        break;
      case 'run.failed':
        handleRunFailed(event.data);
        break;
      case 'run.paused':
        handleRunPaused(event.data);
        break;
    }
    
    res.json({ received: true });
  } catch (error) {
    console.error('Webhook validation failed:', error);
    res.status(401).json({ error: 'Invalid signature' });
  }
});

Estrutura do Evento

Os eventos enviados pelo Triglit seguem esta estrutura:
{
  "type": "run.completed",
  "data": {
    "runId": "run_456",
    "tenantId": "tenant_abc",
    "subTenantId": "sub_tenant_xyz",
    "workflowVersionId": "version_789",
    "timestamp": "2024-01-15T10:00:00Z",
    "status": "succeeded"
  }
}
O campo subTenantId é opcional e estará presente apenas quando a execução ocorrer em um ambiente de sub-tenant. Se não houver sub-tenant associado, este campo não será incluído no payload.

Estrutura por Tipo de Evento

run.started:
{
  "type": "run.started",
  "data": {
    "runId": "run_456",
    "tenantId": "tenant_abc",
    "subTenantId": "sub_tenant_xyz",
    "workflowVersionId": "version_789",
    "timestamp": "2024-01-15T10:00:00Z"
  }
}
run.completed:
{
  "type": "run.completed",
  "data": {
    "runId": "run_456",
    "tenantId": "tenant_abc",
    "subTenantId": "sub_tenant_xyz",
    "workflowVersionId": "version_789",
    "timestamp": "2024-01-15T10:00:00Z",
    "status": "succeeded"
  }
}
run.failed:
{
  "type": "run.failed",
  "data": {
    "runId": "run_456",
    "tenantId": "tenant_abc",
    "subTenantId": "sub_tenant_xyz",
    "workflowVersionId": "version_789",
    "timestamp": "2024-01-15T10:00:00Z",
    "status": "failed",
    "error": "Error message (opcional)"
  }
}
run.cancelled:
{
  "type": "run.cancelled",
  "data": {
    "runId": "run_456",
    "tenantId": "tenant_abc",
    "subTenantId": "sub_tenant_xyz",
    "workflowVersionId": "version_789",
    "timestamp": "2024-01-15T10:00:00Z",
    "status": "cancelled"
  }
}
run.paused:
{
  "type": "run.paused",
  "data": {
    "runId": "run_456",
    "tenantId": "tenant_abc",
    "subTenantId": "sub_tenant_xyz",
    "workflowVersionId": "version_789",
    "timestamp": "2024-01-15T10:00:00Z",
    "status": "paused",
    "pauseReason": "Waiting for user input",
    "resumeToken": "resume_token_123",
    "timeoutAt": "2024-01-15T10:05:00Z"
  }
}
run.resumed:
{
  "type": "run.resumed",
  "data": {
    "runId": "run_456",
    "tenantId": "tenant_abc",
    "subTenantId": "sub_tenant_xyz",
    "workflowVersionId": "version_789",
    "timestamp": "2024-01-15T10:00:00Z",
    "status": "resumed",
    "resumeToken": "resume_token_123"
  }
}

Validação de Assinatura

O Svix envia webhooks com assinaturas nos headers:
  • svix-id: ID único do evento
  • svix-timestamp: Timestamp do evento
  • svix-signature: Assinatura HMAC SHA256
Sempre valide a assinatura do webhook usando o SDK do Svix ou validação manual. Nunca processe webhooks sem validar a assinatura.

Exemplo Completo

const express = require('express');
const { Webhook } = require('svix');

const app = express();
const webhook = new Webhook(process.env.SVIX_SECRET);

app.post('/webhooks/triglit', express.raw({ type: 'application/json' }), async (req, res) => {
  try {
    // Validar assinatura usando Svix
    const payload = webhook.verify(req.body, {
      'svix-id': req.headers['svix-id'],
      'svix-timestamp': req.headers['svix-timestamp'],
      'svix-signature': req.headers['svix-signature']
    });
    
    const event = JSON.parse(payload);
    
    console.log(`Received event: ${event.type}`);
    
    switch (event.type) {
      case 'run.started':
        await handleRunStarted(event.data);
        break;
        
      case 'run.completed':
        await handleRunCompleted(event.data);
        break;
        
      case 'run.failed':
        await handleRunFailed(event.data);
        break;
        
      case 'run.cancelled':
        await handleRunCancelled(event.data);
        break;
        
      case 'run.paused':
        await handleRunPaused(event.data);
        break;
        
      case 'run.resumed':
        await handleRunResumed(event.data);
        break;
    }
    
    res.json({ received: true });
    
  } catch (error) {
    console.error('Webhook error:', error);
    res.status(401).json({ error: 'Invalid signature' });
  }
});

async function handleRunStarted(data) {
  console.log(`Run ${data.runId} started`);
  // Lógica para quando uma execução inicia
}

async function handleRunCompleted(data) {
  console.log(`Run ${data.runId} completed successfully`);
  // Atualizar status no seu sistema
  // await updateOrderStatus(data.runId, 'processed');
}

async function handleRunFailed(data) {
  console.error(`Run ${data.runId} failed:`, data.error);
  // Atualizar status e notificar equipe
  // await updateOrderStatus(data.runId, 'failed');
  // await notifyTeam(data.runId, data.error);
}

async function handleRunCancelled(data) {
  console.log(`Run ${data.runId} was cancelled`);
  // Lógica para execução cancelada
}

async function handleRunPaused(data) {
  console.log(`Run ${data.runId} paused: ${data.pauseReason}`);
  // Salvar resumeToken para retomar depois
  // await saveResumeToken(data.runId, data.resumeToken);
}

async function handleRunResumed(data) {
  console.log(`Run ${data.runId} resumed`);
  // Lógica para quando execução é retomada
}

app.listen(3000);

Retries e Confiabilidade

O Svix gerencia automaticamente retries e entrega confiável de webhooks:
  • Retries automáticos: O Svix retenta automaticamente em caso de falha
  • Entrega garantida: Webhooks são entregues de forma confiável
  • Timeout: Configurável no Svix
  • Dead Letter Queue: Webhooks que falham persistentemente são armazenados
Sempre retorne 200 OK rapidamente após validar a assinatura:
app.post('/webhooks/triglit', async (req, res) => {
  try {
    // Validar assinatura
    const payload = webhook.verify(req.body, {
      'svix-id': req.headers['svix-id'],
      'svix-timestamp': req.headers['svix-timestamp'],
      'svix-signature': req.headers['svix-signature']
    });
    
    // Retornar imediatamente
    res.json({ received: true });
    
    // Processar de forma assíncrona
    processEventAsync(JSON.parse(payload));
  } catch (error) {
    res.status(401).json({ error: 'Invalid signature' });
  }
});

Boas Práticas

Sempre valide assinaturas usando o SDK do Svix. Nunca processe webhooks sem validação.
Torne handlers idempotentes para lidar com retries do Svix. Use o svix-id para detectar duplicatas.
Retorne 200 OK rapidamente após validar a assinatura e processe eventos de forma assíncrona.
Logue todos os eventos recebidos usando o svix-id para rastreabilidade.
Use sempre HTTPS para webhooks em produção. O Svix requer HTTPS para endpoints de produção.
Configure webhooks através do painel do Triglit. Não é necessário usar a API para isso.

SDKs do Svix

O Svix oferece SDKs oficiais para várias linguagens:
  • JavaScript/TypeScript: npm install svix
  • Python: pip install svix
  • Go: go get github.com/svix/svix-libs/go
  • Ruby: gem install svix
  • Java: mvn install svix
  • C#: dotnet add package Svix

Documentação do Svix

Veja a documentação completa do Svix para mais detalhes sobre validação e configuração
Use o Svix CLI ou dashboard para testar webhooks localmente durante desenvolvimento. O Svix também oferece ferramentas para debugging.