Pular para o conteúdo principal
Você recebe callbacks POST de qualquer serviço externo (gateways de pagamento, GitHub, CRMs, etc.), valida o payload e processa o evento. Padrão: rota personalizada + somente POST + MCP desativado + validação de payload.
index.ts
import { define, z } from "@jelou/functions";

export default define({
  name: "webhook-receiver",
  description: "Receives and processes webhooks from external services",
  input: z.object({
    event: z.string(),
    data: z.object({
      id: z.string(),
      status: z.string(),
      metadata: z.record(z.unknown()).optional(),
    }),
  }),
  config: {
    path: "/webhooks/events",
    methods: ["POST"],
    mcp: false,
  },
  handler: async (input, ctx) => {
    ctx.log("Webhook received", {
      event: input.event,
      id: input.data.id,
      requestId: ctx.requestId,
    });

    const secret = ctx.env.get("WEBHOOK_SECRET");

    switch (input.event) {
      case "payment.completed": {
        ctx.log("Payment completed", { id: input.data.id });
        return { acknowledged: true, action: "payment_processed" };
      }
      case "user.created": {
        ctx.log("User created", { id: input.data.id });
        return { acknowledged: true, action: "user_synced" };
      }
      default: {
        ctx.log("Unhandled event", { event: input.event });
        return { acknowledged: true, action: "ignored" };
      }
    }
  },
});

Testes locais

curl -X POST http://localhost:3000/webhooks/events \
  -H "Content-Type: application/json" \
  -d '{"event": "payment.completed", "data": {"id": "pay_123", "status": "success"}}'

Por que funciona dessa forma

  • config.methods: ["POST"] — rejeita GET, PUT, etc. Webhooks são sempre POST.
  • config.mcp: false — não faz sentido expor um webhook como ferramenta de IA.
  • config.path — rota fixa que você configura no serviço externo.
  • O schema input valida a estrutura do payload antes de chegar ao handler.
Este exemplo omite a verificação de assinatura do webhook por brevidade. Em produção, valide a assinatura (por exemplo, HMAC-SHA256 com o header x-webhook-signature) antes de processar o evento.