# Von einem Server

> Erstelle Einsendungen aus einem Backend, einem Skript oder einer Integration mit einem geheimen API-Schlüssel.

Backends, Cronjobs und Integrationen können an denselben Endpunkt senden wie Browser. Füge einen geheimen API-Schlüssel hinzu, damit Ikiform weiß, dass der Post von dir kommt.

## Secret Key erstellen

1. Öffne im Dashboard **API keys** und erstelle einen **secret** Key.
2. Gib ihm den Scope `submissions:write`. Füge `submissions:read` und `forms:read` nur hinzu, wenn derselbe Schlüssel auch Daten aus der [REST API](https://ikiform.com/de/docs/api.md) liest.
3. Kopiere den Schlüssel. Er beginnt mit `ik_sk_` und wird nur einmal angezeigt; Ikiform speichert nur seinen Hash.

## Eine Einsendung senden

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

## Was ein Secret Key ändert

| Prüfung | Ohne Schlüssel | Mit einem Secret Key |
| --- | --- | --- |
| Erlaubte Domains | Gegen `Origin` oder `Referer` geprüft | Übersprungen |
| Ikiform-Menschlichkeitsprüfung | Pflicht, wenn eingeschaltet | Übersprungen |
| Eigene Turnstile-Schlüssel | Token erforderlich | Token weiterhin erforderlich |
| Rate-Limits | Pro Besucher-IP und Formular | Gelten weiterhin, pro IP deines Servers |
| Feldvalidierung und Spam-Bewertung | Laufen | Laufen |

Ein Schlüssel aus einem anderen Workspace, ein widerrufener Schlüssel oder ein Secret Key ohne `submissions:write` bekommt `403 forbidden`. Ein fehlerhafter `Authorization`-Header wird ebenfalls abgelehnt statt ignoriert, sodass ein Tippfehler nie stillschweigend zu einem anonymen Post wird.

> Posts von deinem Server kommen alle von der IP-Adresse deines Servers, sodass Ikiforms Rate-Limits pro Besucher alle Besucher zusammen zählen. Das Preset Standard erlaubt 5 Posts pro Minute pro IP und Formular, was eine viel besuchte Website erreichen kann. Sende aus dem Browser, wenn du kannst, oder wähle das [Rate-Limit](https://ikiform.com/de/docs/rate-limits.md) Relaxed oder Custom für Formulare, die du über einen Server weiterleitest.

## Publishable Keys

Publishable Keys (`ik_pub_`) sind für Browser gedacht. Sie können nur Einsendungen senden, und nur von den Domains, die du beim Schlüssel einträgst. Ein Post mit einem Publishable Key von einer anderen Website bekommt `403 origin_not_allowed`. Sie überspringen weder die Menschlichkeitsprüfung noch die erlaubten Domains des Formulars.

> Leg einen Secret Key nie in Browser-Code, eine mobile App oder ein öffentliches Repository. Widerrufe ihn im Dashboard, wenn er geleakt wird.

## Erneute Versuche

Server versuchen es erneut. Sende einen `Idempotency-Key`, der für das, was du sendest, stabil ist, etwa eine Bestell-ID, dann spielt ein erneuter Versuch die erste Antwort erneut ab, statt ein Duplikat zu erstellen. Siehe [Idempotenz](https://ikiform.com/de/docs/frameworks.md#idempotency).
