> For the complete documentation index, see [llms.txt](https://docs.skail.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.skail.dev/construir/escrever-fluxos/como-disparar-um-evento-pela-api-http.md).

# Como disparar um evento pela API HTTP

Como acordar uma function que está parada em `SkailTask.WaitForEvent`, a partir de um webhook, de uma tela ou de um job. O disparo é um `POST` na API do skail; esta página mostra o padrão completo dos dois lados.

## Pré-requisitos

O cliente HTTP nomeado `skail` configurado como em [Como disparar uma função pela API HTTP](/construir/escrever-fluxos/como-disparar-uma-funcao-pela-api-http.md), com URL base, `skail-key` e `Skail-namespace`.

## 1. Defina o contrato do evento em um lugar só

```csharp
public static class Eventos
{
    public const string PagamentoConfirmado = "PAGAMENTO_CONFIRMADO";
}

public record ConfirmacaoPagamento(bool Aprovado, string TransacaoId, string? MotivoRecusa);
```

O nome vive em uma constante e o payload em um record. Os dois lados (a function e quem dispara) referenciam os mesmos tipos; se estão em projetos diferentes, um pacote compartilhado.

## 2. Espere na function

```csharp
[SkailFunction]
public async SkailTask ProcessarFatura(Guid faturaId)
{
    await EnviarParaCobranca(faturaId);                                   // command: chama o gateway

    var confirmacao = SkailTask.WaitForEvent<ConfirmacaoPagamento>(Eventos.PagamentoConfirmado, faturaId.ToString());
    var prazo       = SkailTask.Delay(TimeSpan.FromHours(48));

    if (await SkailTask.WhenAny(confirmacao, prazo) == prazo)
    {
        await CancelarPorExpiracao(faturaId);
        return;
    }

    var resultado = await confirmacao;
    if (resultado.Aprovado) await LiberarPedido(faturaId);
    else                    await RegistrarRecusa(faturaId, resultado.MotivoRecusa);
}
```

O instance id é o `faturaId`, o mesmo id que o gateway vai devolver no webhook. A espera tem prazo de 48 horas.

## 3. Dispare a partir do webhook

O gateway de pagamento chama o seu endpoint quando o pagamento é processado. O endpoint faz o fire:

```csharp
using System.Net.Http.Json;

[ApiController]
[Route("webhooks/gateway")]
public class GatewayWebhookController : ControllerBase
{
    private readonly HttpClient _skail;

    public GatewayWebhookController(IHttpClientFactory factory) => _skail = factory.CreateClient("skail");

    [HttpPost("pagamento")]
    public async Task<IActionResult> Pagamento([FromBody] NotificacaoGateway notificacao, CancellationToken ct)
    {
        // valide a assinatura do webhook antes de qualquer coisa

        var confirmacao = new ConfirmacaoPagamento(
            Aprovado: notificacao.Status == "approved",
            TransacaoId: notificacao.TransactionId,
            MotivoRecusa: notificacao.DeclineReason);

        var resposta = await _skail.PostAsJsonAsync(
            $"/api/v1/fire/{Eventos.PagamentoConfirmado}/{notificacao.InvoiceId}",
            confirmacao, ct);

        resposta.EnsureSuccessStatusCode();
        return Ok();
    }
}
```

O caminho leva o nome do evento (a constante) e o instance id (o id da fatura que veio no webhook). O corpo é o record, que o skail desserializa no `T` do `WaitForEvent<T>`.

O endpoint não grava nada. O que precisa ser persistido a partir da confirmação (a transação, o status da fatura) é gravado pela function, em um command, depois que o evento chega. Gravar no endpoint e só depois disparar deixa dois registros que podem divergir: se o disparo falhar, o banco diz pago e a function continua esperando. Dentro da execução, a gravação tem o retry e a retomada do skail.

O que você deve ver: no Monitor, a execução sai de aguardando evento, o payload aparece na linha do tempo, e a function continua em `LiberarPedido` ou `RegistrarRecusa`.

## Se o webhook chega antes

O gateway pode responder em segundos, enquanto a function ainda está em `EnviarParaCobranca`. O evento é entregue assim que a execução alcançar o `WaitForEvent`. Você não precisa tratar a ordem.

## Se o webhook falhar ao chamar o skail

Se o `POST` para o skail falhar (rede, 5xx), devolva erro ao gateway para que ele reenvie o webhook, ou retente com backoff. Gateways sérios reenviam; se o seu não reenvia, o retry precisa ser seu. Um fire repetido para uma espera já atendida não faz mal se a function tem uma espera só; se tem várias com o mesmo nome e id, cada fire atende uma.

## Disparar de uma tela

Quando quem dispara é uma pessoa (aprovação, revisão), o padrão é o mesmo: o BFF recebe o clique e faz o fire com o id da solicitação. Ver [Human-in-the-loop](/construir/padroes-e-antipadroes/human-in-the-loop.md).

## Disparar de dentro de uma execução durável

Se uma function precisa acordar outra execução, a chamada HTTP vai em um `[SkailCommand]`, como qualquer integração externa. Não existe uma primitiva do SDK para isso.

## Erros comuns

| Sintoma                                  | Causa                                                                                       | Correção                                             |
| ---------------------------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| Execução continua aguardando após o fire | Nome ou instance id diferentes entre os dois lados (caixa, espaço, `Guid` com e sem hifens) | Constantes compartilhadas; o mesmo id nos dois lados |
| 2xx no fire, nada acontece               | Fire enviado ao namespace de outro environment                                              | Confira `Skail-namespace`                            |
| Function recebe payload com campos nulos | Nomes das propriedades do JSON não batem com o record                                       | Use o mesmo record nos dois lados                    |

## Próximos passos

[POST /api/v1/fire](/construir/api-http/post-api-v1-fire-eventname-instanceid.md) é a referência da rota. [Como esperar com timeout](/construir/escrever-fluxos/como-esperar-com-timeout.md) detalha o prazo. [Eventos externos e correlação](/aprender/fundamentos/eventos-externos-e-correlacao.md) explica o mecanismo.
