# Depuis un serveur

> Créez des soumissions depuis un backend, un script ou une intégration avec une clé API secrète.

Les backends, tâches cron et intégrations peuvent envoyer vers le même endpoint que les navigateurs. Ajoutez une clé API secrète pour qu'Ikiform sache que l'envoi vient de vous.

## Créez une clé secrète

1. Dans le tableau de bord, ouvrez **API keys** et créez une clé **secret**.
2. Donnez-lui la portée `submissions:write`. Ajoutez `submissions:read` et `forms:read` seulement si la même clé lit aussi des données via l'[API REST](https://ikiform.com/fr/docs/api.md).
3. Copiez la clé. Elle commence par `ik_sk_` et n'est affichée qu'une fois ; Ikiform n'en stocke que le hachage.

## Envoyez une soumission

**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']}")
```

## Ce que change une clé secrète

| Contrôle | Sans clé | Avec une clé secrète |
| --- | --- | --- |
| Domaines autorisés | Comparés à `Origin` ou `Referer` | Ignoré |
| Vérification humaine Ikiform | Obligatoire si activée | Ignoré |
| Vos propres clés Turnstile | Token obligatoire | Token toujours obligatoire |
| Limites de débit | Par IP de visiteur et par formulaire | Toujours appliquées, par IP de votre serveur |
| Validation des champs et score de spam | Exécutés | Exécutés |

Une clé d'un autre espace de travail, une clé révoquée ou une clé secrète sans `submissions:write` reçoit `403 forbidden`. Un en-tête `Authorization` mal formé est lui aussi refusé plutôt qu'ignoré, pour qu'une faute de frappe ne transforme jamais l'envoi en envoi anonyme sans que vous le sachiez.

> Les envois depuis votre serveur viennent tous de l'adresse IP de votre serveur, donc les limites de débit par visiteur d'Ikiform comptent tous les visiteurs ensemble. Le préréglage Standard autorise 5 envois par minute par IP et par formulaire, ce qu'un site fréquenté peut atteindre. Envoyez depuis le navigateur quand c'est possible, ou choisissez la [limite de débit](https://ikiform.com/fr/docs/rate-limits.md) Relaxed ou Custom pour les formulaires que vous faites passer par un serveur.

## Clés publiables

Les clés publiables (`ik_pub_`) sont destinées aux navigateurs. Elles peuvent seulement soumettre, et uniquement depuis les domaines listés sur la clé. Un envoi avec une clé publiable depuis un autre site reçoit `403 origin_not_allowed`. Elles ne contournent ni la vérification humaine ni les domaines autorisés du formulaire.

> Ne mettez jamais une clé secrète dans du code navigateur, une app mobile ou un dépôt public. Révoquez-la dans le tableau de bord en cas de fuite.

## Nouvelles tentatives

Les serveurs réessaient. Envoyez une `Idempotency-Key` stable pour ce que vous soumettez, comme un id de commande, et une nouvelle tentative rejouera la première réponse au lieu de créer un doublon. Voir [Idempotence](https://ikiform.com/fr/docs/frameworks.md#idempotency).
