> 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-uma-funcao-pela-api-http.md).

# Como disparar uma função pela API HTTP

O padrão completo para iniciar uma `[SkailFunction]` a partir do seu sistema: um cliente HTTP configurado uma vez, um serviço que dispara com id de negócio, e retry no chamador.

## Pré-requisitos

A URL base da API, a chave e o namespace do environment (tela do environment no portal). O workload publicado com `SKAIL_WORKLOAD=nome:versao` e a function que você quer iniciar.

## 1. Configure o cliente uma vez

No `Program.cs` do sistema que dispara (uma API ASP.NET, um worker, qualquer processo .NET):

```csharp
builder.Services.AddHttpClient("skail", (sp, http) =>
{
    var cfg = sp.GetRequiredService<IConfiguration>().GetSection("skailApi");
    http.BaseAddress = new Uri(cfg["baseUrl"]!);
    http.DefaultRequestHeaders.Add("skail-key", cfg["key"]!);
    http.DefaultRequestHeaders.Add("Skail-namespace", cfg["namespace"]!);
});
```

```json
{
  "skailApi": {
    "baseUrl": "https://SEU_SKAIL_BASE_URL",
    "key": "SUA_SKAIL_KEY",
    "namespace": "SEU_NAMESPACE"
  }
}
```

A chave vem do cofre de segredos, não do arquivo versionado. Uma configuração dessas por environment.

## 2. Escreva o serviço que dispara

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

public class DisparadorSkail
{
    private readonly HttpClient _http;
    private readonly ILogger<DisparadorSkail> _log;

    public DisparadorSkail(IHttpClientFactory factory, ILogger<DisparadorSkail> log)
    {
        _http = factory.CreateClient("skail");
        _log = log;
    }

    public async Task IniciarEmissaoDeFatura(Guid faturaId, CancellationToken ct)
    {
        var caminho = $"/trigger/faturamento/v1.0.0/EmitirFatura/{faturaId}";
        var argumentos = new object[] { faturaId };            // array, na ordem da assinatura

        for (var tentativa = 1; ; tentativa++)
        {
            var resposta = await _http.PostAsJsonAsync(caminho, argumentos, ct);
            if (resposta.IsSuccessStatusCode) return;

            var deveRetentar = (int)resposta.StatusCode == 429 || (int)resposta.StatusCode >= 500;
            if (!deveRetentar || tentativa == 5)
            {
                _log.LogError("Trigger de {Fatura} falhou com {Status}", faturaId, resposta.StatusCode);
                resposta.EnsureSuccessStatusCode();
            }

            await Task.Delay(TimeSpan.FromMilliseconds(200 * Math.Pow(2, tentativa)), ct);
        }
    }
}
```

Registre com `builder.Services.AddScoped<DisparadorSkail>()` e injete no controller que recebe o pedido. Se o seu projeto já usa Polly, a política de retry substitui o laço.

Três decisões estão nesse código. O `id` da execução é o id da fatura: assim a execução é encontrada no Monitor pelo id que o negócio conhece, e um disparo duplicado por engano é visível. O corpo é um array com os argumentos na ordem da assinatura, serializados como `System.Text.Json` serializa cada tipo (um `Guid` vira string). E o retry só acontece para 429 e 5xx; 400, 401, 403 e 404 são erros de configuração ou de chamada, e retentar não resolve.

## 3. Chame a partir do controller

```csharp
[HttpPost("faturas/{faturaId:guid}/emitir")]
public async Task<IActionResult> Emitir(Guid faturaId, [FromServices] DisparadorSkail skail, CancellationToken ct)
{
    await skail.IniciarEmissaoDeFatura(faturaId, ct);
    return Accepted(new { faturaId });
}
```

O que você deve ver: a execução aparece no Monitor com o TaskId igual ao `faturaId`, e a sua aplicação com o runtime começa a processá-la.

## Por que retry aqui

O trigger é a única etapa fora da durabilidade do skail: se a chamada HTTP falhar, a execução não começou e ninguém vai retentar por você. Depois que o trigger é aceito, tudo o que acontece dentro da function é retentado e retomado pelo skail. Por isso o chamador retenta com o mesmo `id`.

## Variações

Function com vários argumentos: `new object[] { pedidoId, valor, new EnderecoDto(...) }`, na ordem da assinatura. Function sem argumentos: `Array.Empty<object>()`. Em Node.js, Python ou shell: o mesmo `POST`, ver [Chamar o skail de qualquer linguagem por REST](/aprender/outras-linguagens/chamar-o-skail-de-qualquer-linguagem-por-rest.md).

## Erros comuns

| Sintoma                         | Causa                                                                       | Correção                                        |
| ------------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------- |
| 401 ou 403                      | Chave ou namespace errados, ou de outro environment                         | Confira os dois na tela do environment          |
| 404                             | `nome`, `versao` ou `funcao` não batem com o publicado                      | Compare com `SKAIL_WORKLOAD` e o nome do método |
| 2xx, mas nada no Monitor        | Namespace de outro environment (a chamada foi aceita em outro lugar)        | Confira o namespace                             |
| 2xx, no Monitor mas não executa | A aplicação não está rodando com esse `SKAIL_WORKLOAD`                      | Suba a aplicação; a execução espera por ela     |
| 400                             | Corpo não é um array, ou um argumento não desserializa no tipo do parâmetro | Confira a ordem e os tipos                      |

## Próximos passos

[POST /trigger](/construir/api-http/post-trigger-workload-versao-funcao-id.md) é a referência da rota. [Como disparar um evento pela API HTTP](/construir/escrever-fluxos/como-disparar-um-evento-pela-api-http.md) usa o mesmo cliente para o fire. [Autenticação e headers](/construir/api-http/autenticacao-e-headers.md) para os códigos de erro.
