# A partir de um servidor

> Crie envios a partir de um backend, script ou integração com uma chave de API secreta.

Backends, cron jobs e integrações podem enviar para o mesmo endpoint que os navegadores. Adicione uma chave de API secreta para o Ikiform saber que o envio é seu.

## Crie uma chave secreta

1. No painel, abra **API keys** e crie uma chave **secret**.
2. Dê a ela o escopo `submissions:write`. Adicione `submissions:read` e `forms:read` só se a mesma chave também for ler dados da [API REST](https://ikiform.com/pt-br/docs/api.md).
3. Copie a chave. Ela começa com `ik_sk_` e é exibida uma única vez; o Ikiform guarda só o hash dela.

## Faça um envio

**Node** (`submit.ts`)

```ts
const response = await fetch("https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${process.env.IKIFORM_SECRET_KEY}`,
    "Idempotency-Key": order.id,
  },
  body: JSON.stringify({ email: order.email, plan: order.plan }),
});

const result = await response.json();
if (!result.ok) throw new Error(`${result.error.code}: ${result.error.message} (${result.request_id})`);
```

**curl** (`Terminal`)

```bash
curl https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx \
  -H "Authorization: Bearer $IKIFORM_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order_1234" \
  -d '{"email":"ada@example.com","plan":"team"}'
```

**Python** (`submit.py`)

```python
import os

import requests

response = requests.post(
    "https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx",
    json={"email": "ada@example.com", "plan": "team"},
    headers={
        "Authorization": f"Bearer {os.environ['IKIFORM_SECRET_KEY']}",
        "Idempotency-Key": "order_1234",
    },
    timeout=10,
)
result = response.json()
if not result["ok"]:
    raise RuntimeError(f"{result['error']['code']}: {result['error']['message']}")
```

## O que uma chave secreta muda

| Verificação | Sem chave | Com chave secreta |
| --- | --- | --- |
| Domínios permitidos | Comparados com `Origin` ou `Referer` | Ignorada |
| Verificação humana do Ikiform | Obrigatória quando ativada | Ignorada |
| Suas próprias chaves do Turnstile | Token obrigatório | Token continua obrigatório |
| Limites de taxa | Por IP de visitante e formulário | Continuam valendo, pelo IP do seu servidor |
| Validação de campos e pontuação de spam | Rodam | Rodam |

Uma chave de outro workspace, uma chave revogada ou uma chave secreta sem `submissions:write` recebe `403 forbidden`. Um header `Authorization` malformado também é recusado em vez de ignorado, então um erro de digitação nunca vira silenciosamente um envio anônimo.

> Envios feitos pelo seu servidor vêm todos do endereço IP do seu servidor, então os limites de taxa por visitante do Ikiform contam todos os visitantes juntos. O preset Standard permite 5 envios por minuto por IP e formulário, o que um site movimentado pode atingir. Envie do navegador quando puder, ou escolha o [limite de taxa](https://ikiform.com/pt-br/docs/rate-limits.md) Relaxed ou Custom para formulários que passam por um servidor.

## Chaves publicáveis

Chaves publicáveis (`ik_pub_`) são para navegadores. Elas só podem enviar, e só a partir dos domínios que você lista na chave. Um envio com chave publicável vindo de qualquer outro site recebe `403 origin_not_allowed`. Elas não pulam a verificação humana nem os domínios permitidos do próprio formulário.

> Nunca coloque uma chave secreta em código de navegador, em um app mobile ou em um repositório público. Revogue-a no painel se ela vazar.

## Novas tentativas

Servidores tentam de novo. Envie um `Idempotency-Key` estável para o que você está enviando, como o id de um pedido, e uma nova tentativa vai repetir a primeira resposta em vez de criar um duplicado. Veja [Idempotência](https://ikiform.com/pt-br/docs/frameworks.md#idempotency).
