Lompat ke konten utama
Dokumentasi AdForm
llms.txt Pusat Bantuan

Kode Error

Daftar lengkap status HTTP dan pesan galat yang benar-benar dikembalikan endpoint ber-API-key AdForm, apa artinya, dan tindakan yang tepat untuk masing-masing.

Semua galat berbentuk JSON dengan satu field:

JSON
{ "error": "Missing scope: products:write" }

Sebagian besar endpoint hanya mengirim field error itu: tanpa kode galat mesin, tanpa request_id, tanpa rincian per-field. Yang membedakan adalah status HTTP ditambah teks error.

Kecualinya /api/order_status.php, yang mengirim dua field tambahan pada galat yang berasal dari endpoint itu sendiri:

JSON
{ "error": "Pesanan tidak ditemukan.", "code": "order_not_found", "request_id": "9f2c41ab" }

code adalah penanda tetap yang aman dijadikan cabang program; request_id untuk penelusuran saat melapor. Daftar lengkapnya di Status Pesanan.

Galat yang berasal dari lapisan bersama di depan endpoint — 401 dan 403 dari pemeriksa kunci API, 429 dari pembatas laju — tetap hanya memuat error, termasuk untuk endpoint tersebut.

Cabangkan program Anda pada status HTTP, bukan pada teks error. Teks bisa berubah kata; status tidak. Pakai teks untuk log dan untuk pesan ke manusia.

Field success tidak dikirim pada response galat. Jangan menguji data.success === false — uji res.ok atau status HTTP.

Daftar di bawah dikumpulkan dari kode yang berjalan di produksi. Cakupannya tiga berkas endpoint yang memeriksa API key: /api/products.php (?action=embed dan ?action=duplicate), /api/customer_lookup.php, serta /api/order_status.php.

#Ringkasan status

StatusArtiUlangi otomatis?
200Berhasil, operasi baca.—
201Berhasil, objek baru dibuat.—
400Permintaan Anda salah bentuk atau tidak lolos validasi.Tidak. Perbaiki request.
401Masalah pada API key.Tidak. Perbaiki konfigurasi.
403Key valid, tapi tidak berhak.Tidak. Perbaiki scope atau status akun.
404Objek tidak ada di tenant pemilik key.Tidak.
405Method HTTP salah. Hanya /api/customer_lookup.php, yang menerima POST saja.Tidak. Perbaiki request.
413Body permintaan lebih dari 4 KB. Hanya /api/customer_lookup.php.Tidak. Perbaiki request.
429Batas laju terlampaui.Ya, setelah menunggu sesuai Retry-After.
500Kesalahan di sisi AdForm.Untuk operasi baca ya, dengan jeda membesar. Untuk operasi tulis, periksa dulu.

Tidak ada 405 pada /api/products.php: yang menentukan operasi di sana adalah nilai action, bukan method HTTP. /api/customer_lookup.php sebaliknya — ia menolak semua method selain POST dengan 405, supaya nomor telepon tidak pernah masuk query string. Tidak ada 402 pada jalur API key.

/api/customer_lookup.php juga tidak pernah membalas 500 untuk kegagalan basis data. Kalau pencarian pesanan gagal di sisi kami, responsnya tetap 200 dengan meta.degraded bernilai true. Lihat Pencarian Pelanggan.

#Galat autentikasi

Semua diperiksa sebelum request menyentuh data produk, dengan urutan seperti di tabel.

StatuserrorPenyebabYang harus dilakukan
401API key required (X-API-Key header)Header X-API-Key tidak dikirim, atau nilainya string kosong.Kirim header. Periksa apakah proxy atau klien HTTP Anda membuang header kustom.
401Malformed API keyNilai key tidak cocok pola adk_ diikuti 48 karakter heksadesimal huruf kecil.Periksa key yang tersalin utuh, tanpa spasi/baris baru, dan tidak ter-uppercase. Diperiksa sebelum menyentuh database.
401Invalid API keyBentuknya benar, tapi tidak ada di database. Salah ketik, atau key sudah dihapus.Pastikan Anda memakai key untuk lingkungan yang benar. Kalau hilang, minta key baru.
401API key revokedKey ada, tapi sudah dinonaktifkan.Key ini tidak akan hidup lagi. Minta key baru.
401API key expiredKey punya tanggal kedaluwarsa dan tanggal itu sudah lewat menurut jam server.Minta key baru, atau minta key tanpa masa berlaku.
403Tenant inactiveAkun tenant pemilik key sedang nonaktif.Ini urusan akun, bukan integrasi. Pemilik akun perlu menghubungi AdForm.

Jangan mengulang otomatis satu pun dari daftar ini. Semuanya kesalahan konfigurasi, bukan gangguan sementara — mengulang hanya menghabiskan jatah batas laju Anda.

Tidak ada header WWW-Authenticate pada response 401.

#Galat scope

StatuserrorPenyebab
403Missing scope: products:readKey valid, tapi tidak memuat scope products:read. Muncul pada action=embed.
403Missing scope: products:writeKey valid, tapi tidak memuat scope products:write. Muncul pada action=duplicate.
403Missing scope: customers:readKey valid, tapi tidak memuat scope customers:read. Muncul pada POST /api/customer_lookup.php.

Pencocokan scope adalah kecocokan string persis. Tidak ada pola glob — products:* bukan scope yang sah dan tidak cocok dengan apa pun. Key yang memuat * melewati semua pemeriksaan scope.

Pesan hanya menyebut satu scope pertama yang kurang, bukan daftar lengkap yang dibutuhkan.

403 di sini permanen sampai key diganti. Minta key baru dengan scope yang sesuai; scope key yang sudah ada tidak bisa ditambah lewat API.

#Galat batas laju

StatuserrorHeader tambahan
429Terlalu banyak permintaan. Coba lagi nanti.Retry-After: <detik>
HTTP
HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json; charset=utf-8

{"error":"Terlalu banyak permintaan. Coba lagi nanti."}

Ini satu-satunya galat yang layak diulang otomatis. Tunggu selama nilai Retry-After (dalam detik), lalu coba lagi, dengan jeda yang membesar kalau tetap kena.

Pemeriksaan batas laju berjalan sebelum pemeriksaan API key. Request dengan key salah pun tetap memakan jatah. Jangan memakai percobaan berulang untuk menebak key atau ID — Anda hanya akan mengunci IP Anda sendiri.

Tidak ada header sisa kuota (X-RateLimit-Remaining dan sejenisnya). Rinciannya di Batas Penggunaan.

#Galat validasi

Semua berstatus 400.

#Umum

errorOperasiPenyebab
id requiredembed, duplicateQuery id tidak dikirim, bukan angka, atau ≤ 0.
Unknown action: <nilai>—Nilai action bukan embed atau duplicate. Contoh: {"error":"Unknown action: list"}.
phone wajib diisiPencarian PelangganField phone tidak ada, bukan nilai skalar, atau hanya spasi.
phone tidak validPencarian PelangganSetelah dibersihkan, nomornya tidak menghasilkan bentuk yang bisa dicocokkan.

#Khusus pencarian pelanggan

Selain dua baris 400 di atas, endpoint ini punya dua status yang tidak muncul di /api/products.php:

StatuserrorPenyebab
405Method not allowedMethod bukan POST. Disengaja: nomor telepon tidak boleh masuk query string.
413Payload too largeBody lebih dari 4 KB, dihitung dari header Content-Length maupun dari byte yang benar-benar dibaca.

#Khusus duplikat produk

errorPenyebab
name requiredBody tidak memuat name, atau name hanya spasi. Sering kali penyebab sebenarnya adalah body dikirim sebagai form-encoded — server hanya membaca JSON.
cannot derive slug from nameslug tidak dikirim dan name tidak memuat karakter yang bisa dijadikan slug (misalnya hanya simbol atau hanya karakter non-latin). Kirim slug sendiri.

#Validasi matriks harga varian

Pemeriksaan ini ada supaya form tidak pernah menagih harga yang salah. Semua dibalas 400. <label> diisi variant_prices atau variant_compare_prices, sesuai bagian mana yang bermasalah.

errorPenyebab
Harga varian harus daftar angka untuk 1 variasi.Produk hanya punya satu variasi, tapi variant_prices dikirim sebagai array bersarang. Untuk satu variasi, bentuknya daftar angka datar.
Setiap variasi minimal punya 1 opsi.Ada variasi dengan options kosong atau tidak berbentuk array.
<label> bentuk matriks tidak sesuai jumlah opsi variasi.Kedalaman atau jumlah elemen matriks tidak persis sama dengan jumlah opsi tiap variasi. Dua variasi berukuran 2×3 menuntut 2 baris berisi 3 angka.
<label> nilai sel harus angka.Ada sel daun yang berisi array, bukan angka — biasanya matriks bersarang satu tingkat terlalu dalam.
<label> tiap kombinasi wajib diisi harga lebih dari 0 (ada sel kosong/0).Ada sel variant_prices yang kosong, 0, atau bukan angka positif. Berlaku untuk variant_prices saja; pada variant_compare_prices nilai 0 diperbolehkan dan berarti "tanpa harga coret".

Contoh utuh:

JSON
{ "error": "variant_prices bentuk matriks tidak sesuai jumlah opsi variasi." }

#Galat objek tidak ditemukan

StatuserrorOperasiPenyebab
404Product not foundembedTidak ada produk dengan id tersebut di tenant pemilik key.
404Source product not foundduplicateTidak ada produk sumber dengan id tersebut di tenant pemilik key.

Objek milik tenant lain juga dibalas 404, bukan 403. Jadi 404 berarti salah satu dari dua hal: ID-nya memang tidak ada, atau ID itu milik tenant lain. Dari luar keduanya tidak bisa dibedakan, dan itu disengaja.

#Galat sisi AdForm

StatuserrorPenyebab
500Terjadi kesalahan sistem. Coba beberapa saat lagi.Pengecualian yang tidak tertangani di sisi kami. Pesan sengaja umum; rinciannya masuk ke log internal AdForm.

Kalau Anda menemukan 500 yang berulang, laporkan lewat Pusat Bantuan dan sertakan waktu kejadian (dengan zona waktu), URL yang dipanggil, dan 12 karakter pertama key yang dipakai (adk_0123456). Jangan mengirim key utuh.

Status 502, 503, dan 504 bisa muncul dari lapisan web server atau CDN sebelum kode AdForm dijalankan. Body-nya belum tentu JSON — jangan berasumsi setiap response bisa di-parse sebagai JSON. Perlakukan sebagai gangguan sementara.

#Kesalahan yang tidak menghasilkan galat

Dua hal ini gagal tanpa pesan yang mengarah ke penyebabnya. Kami tulis supaya Anda tidak menghabiskan waktu mencarinya:

  • Body form-encoded. Server hanya membaca body sebagai JSON. Kalau Anda mengirim application/x-www-form-urlencoded, semua field dianggap tidak ada dan Anda melihat 400 name required untuk name yang jelas-jelas sudah Anda kirim.
  • Lupa action. Tanpa query action, request tidak masuk ke jalur API key sama sekali, melainkan ke jalur dashboard yang memakai sesi login. Header X-API-Key Anda diabaikan di jalur itu, dan POST dibalas 401 {"error":"Unauthorized"} — pesan yang membingungkan kalau Anda mengira key-nya yang bermasalah. Periksa action sebelum memeriksa key.

#Pola penanganan yang kami sarankan

JavaScript
async function callAdForm(url, init = {}) {
  const res = await fetch(url, {
    ...init,
    headers: {
      'X-API-Key': process.env.ADFORM_API_KEY, // hanya di server
      Accept: 'application/json',
      ...init.headers,
    },
  });

  // 502/503/504 bisa membalas HTML, bukan JSON.
  const text = await res.text();
  let body;
  try { body = JSON.parse(text); } catch { body = { error: text.slice(0, 200) }; }

  if (res.ok) return body;

  const err = new Error(`AdForm ${res.status}: ${body.error ?? 'tanpa pesan'}`);
  err.status = res.status;
  err.retryAfter = Number(res.headers.get('Retry-After')) || null;
  // 429 → tunggu err.retryAfter detik lalu ulangi.
  // 5xx pada operasi baca → ulangi dengan jeda membesar.
  // 4xx lain → hentikan, ini kesalahan konfigurasi atau data.
  err.retryable = res.status === 429 || res.status >= 500;
  throw err;
}

Ketik minimal dua huruf.

↑↓ pindah Enter buka Esc tutup