# Dari server

> Buat kiriman dari backend, skrip, atau integrasi dengan secret API key.

Backend, cron job, dan integrasi bisa mengirim ke endpoint yang sama dengan browser. Tambahkan secret API key agar Ikiform tahu kiriman itu dari Anda.

## Buat secret key

1. Di dashboard, buka **API keys** dan buat key **secret**.
2. Beri scope `submissions:write`. Tambahkan `submissions:read` dan `forms:read` hanya jika key yang sama juga membaca data dari [REST API](https://ikiform.com/id/docs/api.md).
3. Salin key-nya. Key diawali `ik_sk_` dan hanya ditampilkan sekali; Ikiform hanya menyimpan hash-nya.

## Membuat kiriman

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

## Apa yang diubah secret key

| Pemeriksaan | Tanpa key | Dengan secret key |
| --- | --- | --- |
| Domain yang diizinkan | Dicocokkan dengan `Origin` atau `Referer` | Dilewati |
| Pemeriksaan manusia Ikiform | Wajib saat diaktifkan | Dilewati |
| Key Turnstile Anda sendiri | Token wajib | Token tetap wajib |
| Rate limit | Per IP pengunjung dan formulir | Tetap berlaku, per IP server Anda |
| Validasi field dan penilaian spam | Berjalan | Berjalan |

Key dari workspace lain, key yang dicabut, atau secret key tanpa `submissions:write` mendapat `403 forbidden`. Header `Authorization` yang salah format juga ditolak, bukan diabaikan, jadi salah ketik tidak pernah diam-diam turun menjadi kiriman anonim.

> Kiriman dari server Anda semuanya berasal dari alamat IP server Anda, jadi rate limit per pengunjung milik Ikiform menghitung semua pengunjung sekaligus. Preset Standard mengizinkan 5 kiriman per menit per IP dan formulir, yang bisa tercapai oleh situs yang ramai. Kirim dari browser jika bisa, atau pilih [rate limit](https://ikiform.com/id/docs/rate-limits.md) Relaxed atau Custom untuk formulir yang Anda proxy lewat server.

## Publishable key

Publishable key (`ik_pub_`) ditujukan untuk browser. Key ini hanya bisa mengirim, dan hanya dari domain yang Anda cantumkan di key. Kiriman dengan publishable key dari situs lain mendapat `403 origin_not_allowed`. Key ini tidak melewati pemeriksaan manusia maupun domain yang diizinkan milik formulir.

> Jangan pernah menaruh secret key di kode browser, aplikasi seluler, atau repository publik. Cabut di dashboard jika bocor.

## Percobaan ulang

Server melakukan percobaan ulang. Kirim `Idempotency-Key` yang stabil untuk hal yang Anda kirim, seperti ID pesanan, maka percobaan ulang akan mendapat respons pertama lagi alih-alih membuat duplikat. Lihat [Idempotensi](https://ikiform.com/id/docs/frameworks.md#idempotency).
