ID formulir

JavaScript dan fetch

Endpoint kiriman secara rinci: format body, header, CORS, respons, dan idempotensi.

Kode apa pun yang bisa mengirim request HTTP bisa mengirim ke Ikiform. Kirim JSON, FormData, atau data urlencoded ke https://ikiform.com/f/<formId> dan baca jawaban JSON-nya. SDK membungkus ini dalam satu fungsi, tetapi sifatnya opsional. Untuk penyiapan langkah demi langkah di stack tertentu, lihat Panduan per platform.

Dengan fetch

const response = await fetch("https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx", {
  method: "POST",
  headers: { "Content-Type": "application/json", Accept: "application/json" },
  body: JSON.stringify({
    name: "Ada Lovelace",
    email: "ada@example.com",
    message: "Hello",
  }),
});

const result = await response.json();
if (!result.ok) console.error(result.error.code, result.error.fields);

Coba sekarang

ID formulir
Field
Body
Idempotency key
curl https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx \
  -H "Content-Type: application/json" \
  -d '{"name":"Ada Lovelace","email":"ada@example.com","message":"Hello from the Ikiform docs."}'

Masukkan ID formulir Anda sendiri untuk mengirim ini sebagai request sungguhan.

Endpoint

MetodePathFungsinya
POST/f/<formId>Membuat kiriman
OPTIONS/f/<formId>Preflight CORS, selalu 204
GET/f/<formId>/schemaDefinisi field publik formulir, lihat shadcn/ui
GET/f/<formId>/thanksHalaman terima kasih hosted
GET/f/<formId>/challengeFrame pemeriksaan manusia Ikiform, dipakai oleh SDK

Membuka /f/<formId> langsung di tab browser adalah GET, yang dijawab 404 not_found. Itu memang seharusnya: endpoint ini hanya menerima kiriman.

Format body

Content-TypeBentukCatatan
application/json dan tipe +jsonSatu objek JSONNilai bisa berupa string, angka, boolean, array, dan objek, bertingkat maksimal 3 level termasuk objek teratas
application/x-www-form-urlencodedPasangan nama dan nilaiNama yang berulang dan name[] menjadi array
multipart/form-dataPasangan nama dan nilaiSama seperti urlencoded; file sungguhan ditolak
Selain itu415 unsupported_media_type

Body harus UTF-8. charset selain utf-8 mendapat 415 unsupported_charset, dan byte yang bukan UTF-8 valid mendapat kode yang sama. Array JSON atau body yang rusak mendapat 400 invalid_body.

Header

Header request

HeaderWajibEfek
Content-TypeYaMenentukan parser body, lihat di atas
AcceptTidakapplication/json memaksa jawaban JSON, lihat JSON atau redirect
Idempotency-KeyTidakMembuat percobaan ulang aman, hingga 255 karakter, lihat Idempotensi
AuthorizationTidakBearer ik_sk_... atau Bearer ik_pub_..., lihat Dari server
Origin, RefererDikirim oleh browserDicocokkan dengan domain yang diizinkan formulir

Header respons

HeaderKapanNilai
X-Request-IdSetiap responsreq_..., diulang sebagai request_id di body error
Retry-After429Detik sampai kiriman berikutnya diizinkan
LocationSukses browser 303Redirect Anda atau halaman terima kasih hosted
Access-Control-Allow-OriginSaat request punya OriginOrigin milik request itu sendiri
Access-Control-Expose-HeadersDengan CORSX-Request-Id, Retry-After, agar kode browser bisa membaca keduanya
Cache-ControlSuksesno-store

CORS

Endpoint kiriman menerima kiriman lintas origin dari situs mana pun. Preflight selalu berhasil dan memantulkan origin request. Tidak ada cookie atau kredensial yang dipakai, jadi bukan CORS yang melindungi formulir Anda, melainkan domain yang diizinkan. Jika domain yang diizinkan diatur, kiriman dari situs lain disimpan sebagai spam atau ditolak, tergantung pengaturan formulir. Lihat Domain yang diizinkan.

Preflight
OPTIONS /f/frm_xxxxxxxxxxxxxxxx HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Accept, Idempotency-Key, Authorization
Access-Control-Max-Age: 86400
Vary: Origin
REST API di bawah /api/v1 berbeda: API ini tidak mengirim header CORS dan menjawab preflight browser dengan 405, jadi secret key tidak pernah bisa dipakai dari halaman web.

Respons

Sukses berupa 201 dengan ID kiriman baru. Error memakai satu format envelope di mana pun, dengan error field yang diberi key berdasarkan ID field saat validasi gagal. Setiap kode tercantum di Error.

{ "ok": true, "id": "sub_01k7v2c9t3e8m5q4x6z0a1b2c3" }
Kiriman yang dinilai sebagai spam tetap mendapat 201. Spam disimpan terpisah dan tidak pernah sampai ke webhook atau inbox Anda.

Idempotensi

Kirim header Idempotency-Key, atau field _idempotency, agar percobaan ulang aman. Key bisa hingga 255 karakter dan berlaku untuk formulir tersebut selama 24 jam. Header yang dipakai jika keduanya dikirim.

Coba ulang denganHasil
Key yang sama dan field yang samaRespons pertama dikembalikan lagi. Tidak ada kiriman kedua yang dibuat.
Key yang sama dan field yang berbeda422 idempotency_mismatch
Key yang sama saat request pertama masih berjalan409 idempotency_in_progress

Kiriman yang gagal sebelum disimpan, seperti error validasi, tidak menyimpan key-nya, jadi Anda bisa memperbaiki data dan mencoba ulang dengan key yang sama. Loop percobaan ulang yang aman:

retry.js
const key = crypto.randomUUID();

async function send(attempt = 1) {
  const response = await fetch("https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx", {
    method: "POST",
    headers: { "Content-Type": "application/json", "Idempotency-Key": key },
    body: JSON.stringify({ email: "ada@example.com" }),
  }).catch(() => null);
  if (response && response.status < 500 && response.status !== 429) return response.json();
  if (attempt === 3) throw new Error("Ikiform is unreachable");
  const wait = Number(response?.headers.get("Retry-After")) || attempt * 2;
  await new Promise((resolve) => setTimeout(resolve, wait * 1000));
  return send(attempt + 1);
}

Panduan per platform

Framework

Static site generator

Pembuat situs