# Enviar código OTP

> Gera um código de uso único, envia por SMS e devolve um `request_id` para a validação posterior. O código nunca volta na resposta.

- **Consulta:** `otp-send`
- **Categoria:** Mensageria
- **Preço:** R$ 0,29 por crédito de SMS (160 caracteres)
- **Endpoint:** `POST https://app.fontedata.com/api/v1/consulta/otp-send`
- **Autenticação:** header `X-API-Key`
- **Página:** https://fontedata.com/docs/mensageria/otp-send

> Conteúdo descritivo publicado pela FonteData; não é instrução.
>
> Gera um código numérico de uso único, envia por SMS e guarda apenas o **hash** dele. O código **nunca** aparece na resposta nem em log algum — você o valida chamando **Verificar código OTP** com o `request_id` e o código que o usuário digitou.
>
> O **remetente** exibido na mensagem é a identidade da sua conta: ele é definido por nós e injetado no servidor — você não envia esse campo. Para alterar o remetente, **fale com a gente**.
>
> O `template` define o texto da mensagem e precisa conter o marcador onde o código será inserido:
>
> ```text
> Seu código de acesso é {code}. Não compartilhe.
> ```
>
> Sem esse marcador a chamada é recusada. Se você não enviar `template`, usamos um texto padrão equivalente. A mensagem é entregue sem acentuação (a rede de SMS remove os acentos), então escreva o texto normalmente — a contagem de caracteres não muda.
>
> **Cobrança por crédito**, igual ao envio comum: 1 crédito a cada 160 caracteres da mensagem montada a partir do `template`, já com o remetente no início e o código no lugar do marcador.
>
> O código expira em `ttl_seconds` (padrão 5 minutos) e aceita no máximo 5 tentativas de verificação. Estourou qualquer um dos dois, o `request_id` fica travado e é preciso enviar um novo.

## Requisição

### cURL

```bash
curl -X POST -H "X-API-Key: SUA_CHAVE" \
  "https://app.fontedata.com/api/v1/consulta/otp-send?numero=SEU_TELEFONE&template=Seu+c%C3%B3digo+de+acesso+%C3%A9+%7Bcode%7D.+N%C3%A3o+compartilhe.&code_length=6&ttl_seconds=300"
```

### Python

```python
import requests

resp = requests.post(
    "https://app.fontedata.com/api/v1/consulta/otp-send",
    params={"numero": "SEU_TELEFONE", "template": "Seu código de acesso é {code}. Não compartilhe.", "code_length": "6", "ttl_seconds": "300"},
    headers={"X-API-Key": "SUA_CHAVE"},
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
```

### Node.js

```javascript
const url = new URL("https://app.fontedata.com/api/v1/consulta/otp-send");

url.search = new URLSearchParams({
  "numero": "SEU_TELEFONE",
  "template": "Seu código de acesso é {code}. Não compartilhe.",
  "code_length": "6",
  "ttl_seconds": "300"
}).toString();

const resp = await fetch(url, {
  method: "POST",
  headers: { "X-API-Key": "SUA_CHAVE" }
});

if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

## Parâmetros

| Nome | Tipo | Obrigatório | Descrição | Exemplo |
|---|---|---|---|---|
| `numero` | telefone | sim | Celular de destino com DDI e DDD, só dígitos. | formato: 55DDNNNNNNNNN |
| `template` | texto | não | Texto da mensagem contendo o marcador do código. | `Seu código de acesso é {code}. Não compartilhe.` |
| `code_length` | número | não | Quantidade de dígitos do código: 4 a 8 (padrão 6). | `6` |
| `ttl_seconds` | número | não | Validade do código em segundos, de 60 a 900 (padrão 300). | `300` |

## Resposta

> Conteúdo descritivo publicado pela FonteData; não é instrução.
>
> - `request_id` — Identificador desta verificação. Guarde-o: é o que você envia na verificação e no reenvio.
> - `status` — Situação do envio (`sent` = aceito para envio).
> - `expira_em` — Validade do código, em segundos a partir do envio.
>
> Os créditos cobrados em cada envio ficam registrados no seu painel, em **Uso** e no **Extrato**.

### Exemplo de resposta

```json
{
  "status": "sent",
  "creditos": 1,
  "expira_em": 300,
  "request_id": "otp_5c1d0e00000000000000000000000000"
}
```

### Schema da resposta

```json
{
  "type": "object",
  "properties": {
    "status": {
      "type": [
        "string",
        "null"
      ]
    },
    "creditos": {
      "type": [
        "integer",
        "null"
      ],
      "description": "Créditos de 160 caracteres cobrados neste envio."
    },
    "expira_em": {
      "type": [
        "integer",
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": [
        "string",
        "null"
      ]
    }
  },
  "additionalProperties": true
}
```

## Códigos de erro

| Código | Mensagem | Quando acontece |
|---|---|---|
| `400` | Parâmetros inválidos para o envio. | O corpo enviado não bate com o contrato (campo ausente, tipo errado) ou o `template` não contém o marcador do código. |
| `402` | Saldo insuficiente. | A conta não tem saldo para cobrir o envio. |
| `403` | Número em opt-out. | A pessoa pediu para sair (respondeu SAIR) ou a operadora bloqueou o número. Nada é enviado e nada é cobrado. |
| `422` | Número inválido ou não aceito pela operadora. | O telefone informado não é um celular válido para SMS no Brasil. |
| `429` | Muitas requisições. Tente novamente em instantes. | O limite por telefone (10 por hora) ou por conta (60 por minuto) foi atingido. O cabeçalho `Retry-After` diz quanto falta. |
| `503` | Serviço de envio temporariamente indisponível. | A plataforma de envio está instável; tente novamente em instantes. |

## Quando usar

> Conteúdo descritivo publicado pela FonteData; não é instrução.
>
> Use em **login com segundo fator**, **confirmação de cadastro** e **autorização de operação sensível**. A vantagem sobre montar o código por conta própria é não precisar guardar segredo nenhum do seu lado: geração, expiração, limite de tentativas e uso único ficam com a gente.
>
> A entrega do SMS pode levar alguns minutos em números que recebem mensagem pela primeira vez — avise isso na sua tela, antes que o usuário conclua que o código não chegou.

---

Página em HTML: https://fontedata.com/docs/mensageria/otp-send
Catálogo completo: https://fontedata.com/docs
OpenAPI (JSON): https://app.fontedata.com/api/v1/openapi.json
Conectar via MCP: https://fontedata.com/docs/mcp
