> ## Documentation Index
> Fetch the complete documentation index at: https://docs.switchbord.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Envios transacionais de template

> Envie templates Utility aprovados do WhatsApp por telefone ou id de destinatário externo a partir de sistemas externos.

Os envios transacionais de template permitem que sistemas externos confiáveis disparem mensagens esperadas do WhatsApp por meio do Switchbord. O endpoint é projetado para mensagens Utility, como recibos de pagamento, recibos de parcelas, confirmações de reserva, vouchers e outros eventos operacionais esperados pelo cliente.

<Warning>
  Este endpoint não é uma API de marketing em massa. O Switchbord valida o workspace do chamador, o status do template e a categoria do template antes de enfileirar um envio. Use templates `UTILITY` aprovados para fluxos transacionais.
</Warning>

## Endpoint

```text theme={null}
POST /api/v1/template-sends
```

O endpoint reside na aplicação da API. Workspaces hospedados chamam:

```text theme={null}
https://api.switchbord.ai/api/v1/template-sends
```

Implantações auto-hospedadas devem substituir o host pelo seu domínio de API.

## Autenticação

Use uma API key do Switchbord com escopo definido para o workspace. O workspace é resolvido a partir da API key; não envie ids de workspace no corpo da requisição.

```http theme={null}
Authorization: Bearer sk_live_...
Content-Type: application/json
Idempotency-Key: receipt-event-123
```

Você também pode enviar a chave de idempotência como `idempotencyKey` no corpo JSON. Prefira o header quando o sistema upstream suportar isso.

## Formato da requisição

```json theme={null}
{
  "templateName": "payment_receipt_link",
  "templateLocale": "it",
  "recipient": {
    "phoneE164": "+393331234567",
    "externalId": "traveller-123",
    "name": "Giulia Rossi"
  },
  "variables": {
    "body": {
      "1": "Giulia",
      "2": "R-1001",
      "3": "€ 240,00"
    },
    "buttons": {
      "url": [
        { "index": 0, "suffix": "R-1001" }
      ]
    }
  },
  "metadata": {
    "source": "booking-system",
    "eventType": "payment.receipt.created"
  }
}
```

| Campo                  | Tipo   | Obrigatório                                                                           | Notas                                                                                                                   |
| ---------------------- | ------ | ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `templateName`         | string | Sim                                                                                   | Deve resolver para um template Utility aprovado, visível ao workspace do chamador.                                      |
| `templateLocale`       | string | Não                                                                                   | Locale da Meta, como `it`, `it_IT` ou `en_US`. Se omitido, a busca do template usa o comportamento padrão do workspace. |
| `recipient.phoneE164`  | string | Sim, a menos que a busca por contato/id externo seja fornecida por um contrato futuro | Telefone no formato E.164.                                                                                              |
| `recipient.externalId` | string | Não                                                                                   | Id de cliente externo a ser persistido no contato resolvido.                                                            |
| `recipient.name`       | string | Não                                                                                   | Nome de exibição para o contexto de contato recém-criado/resolvido.                                                     |
| `variables`            | object | Não                                                                                   | Valores de body/header/button compilados nos componentes do template da Meta.                                           |
| `components`           | object | Não                                                                                   | Alias para `variables`; use um ou outro.                                                                                |
| `idempotencyKey`       | string | Recomendado                                                                           | Evita envios duplicados para o mesmo evento upstream.                                                                   |
| `metadata`             | object | Não                                                                                   | Armazenado com a mensagem para contexto de auditoria/debug. Não inclua segredos.                                        |

## Respostas

Uma requisição bem-sucedida enfileira um job de saída `message.dispatch` e retorna as identidades do Switchbord para auditoria e reconciliação.

Novos envios retornam HTTP `201`:

```json theme={null}
{
  "data": {
    "contactId": "contact_123",
    "conversationId": "conversation_123",
    "messageId": "message_123",
    "clientMessageId": "receipt-event-123",
    "status": "queued",
    "reused": false,
    "idempotent": true
  }
}
```

Se a mesma chave de idempotência for enviada novamente, o Switchbord retorna HTTP `200` com a identidade da mensagem existente e `reused: true`, em vez de criar um envio duplicado.

## Variáveis

### Variáveis de body

Para templates posicionais, use chaves numéricas baseadas em 1:

```json theme={null}
{
  "variables": {
    "body": {
      "1": "Giulia",
      "2": "R-1001",
      "3": "€ 240,00"
    }
  }
}
```

Variáveis de body nomeadas são suportadas pelo compilador transacional interno do Switchbord para mapeamentos de webhooks entrantes, mas a rota pública da API atualmente aceita apenas variáveis de body posicionais. Use chaves numéricas de body ou um array ao chamar `POST /api/v1/template-sends` diretamente.

### Variáveis de botão de URL dinâmica

Para templates com um botão de URL como `https://example.com/r/{{1}}`, forneça o sufixo dinâmico pelo índice do botão, baseado em 0:

```json theme={null}
{
  "variables": {
    "buttons": {
      "url": [
        { "index": 0, "suffix": "R-1001" }
      ]
    }
  }
}
```

`text` e `suffix` são aceitos como aliases. O valor não pode ser vazio.

### Variáveis de header de documento

Para templates com um header DOCUMENT, forneça um link HTTPS público. `filename` é opcional, mas recomendado.

```json theme={null}
{
  "variables": {
    "header": {
      "document": {
        "link": "https://cdn.example.com/receipts/R-1001.pdf",
        "filename": "R-1001.pdf"
      }
    }
  }
}
```

Links de documento devem usar HTTPS. Links inválidos ou não-HTTPS são rejeitados antes do enfileiramento.

## Respostas de erro

| HTTP  | Erro                            | Significado                                                                              |
| ----- | ------------------------------- | ---------------------------------------------------------------------------------------- |
| `400` | `invalid_json`                  | O corpo da requisição não pôde ser interpretado como JSON.                               |
| `400` | `invalid_request`               | O JSON foi interpretado, mas não correspondeu ao schema do endpoint.                     |
| `400` | `template_not_approved`         | O template existe, mas não foi aprovado pela Meta.                                       |
| `400` | `template_category_not_allowed` | O template não é Utility; envios transacionais são, por padrão, exclusivos para Utility. |
| `400` | `invalid_media_link`            | Um link de documento ou imagem está ausente, inválido ou não é HTTPS.                    |
| `400` | `missing_button_url_variable`   | Uma variável de botão de URL dinâmica é obrigatória, mas está vazia.                     |
| `401` | `missing_authorization`         | Header `Authorization: Bearer ...` ausente.                                              |
| `403` | `invalid_or_insufficient_key`   | A API key é inválida ou não possui o escopo `data_write`.                                |
| `404` | `template_not_found`            | O nome/locale do template não pôde ser resolvido para o workspace.                       |
| `429` | Acesso à API negado             | O middleware de rate/segurança da API pública negou a requisição.                        |

Reutilizações idempotentes não são erros. Elas retornam HTTP `200` com `data.reused: true`.

## Notas operacionais

* O worker ainda é responsável pelo envio final à Meta. A resposta da API significa que a mensagem foi aceita na outbox do Switchbord, não necessariamente entregue pela Meta.
* Transições de entrega (`queued`, `sent`, `delivered`, `read`, `failed`) ficam visíveis nos registros de mensagem/conversa e nos eventos de status de webhook.
* Não inclua dados brutos de cartão, tokens privados de recibo ou segredos de longa duração nas variáveis de template ou em metadata. Prefira ids de recibo curtos ou URLs pré-assinadas com expiração adequada.

## Guias relacionados

* [Guia do link de recibo](/pt-BR/guides/receipt-link-webhook)
* [Guia do recibo em PDF](/pt-BR/guides/pdf-receipt-webhook)
* [Webhooks entrantes](/pt-BR/api-reference/inbound-webhooks)
