IDA Labs API
Search, jawaban AI, ekstraksi halaman, dan riset web untuk aplikasi dan agen AI, dioptimalkan untuk konten Indonesia. Satu API key, respons JSON, dan kredit yang transparan.
Quickstart
- Buat akun & API key. Daftar di dashboard, buka menu Keys, lalu klik Buat key. Key lengkap (
ida_live_…, 57 karakter) hanya ditampilkan sekali. Salin dan simpan di tempat aman. - Simpan key sebagai environment variable. Jangan menaruh key di kode frontend atau repo publik.
export IDA_API_KEY="<API_KEY>" # ganti dengan key Anda (ida_live_...)- Panggil endpoint Search.
curl "https://api-ida.arywibowo.id/api/v1/search?q=harga+beras+hari+ini&limit=5" \
-H "Authorization: Bearer $IDA_API_KEY"import os, requests
r = requests.get(
"https://api-ida.arywibowo.id/api/v1/search",
params={"q": "harga beras hari ini", "limit": 5},
headers={"Authorization": f"Bearer {os.environ['IDA_API_KEY']}"},
timeout=60,
)
r.raise_for_status()
print(r.json())const params = new URLSearchParams({ q: "harga beras hari ini", limit: "5" });
const r = await fetch(`https://api-ida.arywibowo.id/api/v1/search?${params}`, {
headers: { Authorization: `Bearer ${process.env.IDA_API_KEY}` },
});
if (!r.ok) throw new Error((await r.json()).error?.message);
console.log(await r.json());Setiap respons menyertakan sisa kredit di header x-ida-credits-remaining dan pemakaian permintaan itu di usage.credits.
Autentikasi
Semua endpoint kecuali /health membutuhkan API key. Kirim key di header Authorization (disarankan) atau x-api-key.
Authorization: Bearer ida_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# atau
x-api-key: ida_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxJumlah key aktif dibatasi per plan (Free: 1 key). Prefix ida_live_xxxxxxxx yang tampil di daftar key hanya untuk identifikasi, bukan key yang bisa dipakai.
Base URL & format
https://api-ida.arywibowo.id/api/v1- Semua respons berformat JSON (UTF-8). Body POST harus
Content-Type: application/jsondengan headerContent-Length(chunked tidak didukung), maksimal 1 MB. - Waktu dalam ISO 8601 UTC. Kirim header
x-request-idsendiri jika ingin melacak permintaan; jika tidak, server membuatkannya. - Hasil yang identik di-cache sementara. Respons dari cache ditandai
"cached": truedan biaya dasarnya gratis.
Search
/search1 kredit · +1 basic / +3 advancedPencarian web real-time dari beberapa mesin pencari, diurutkan menurut relevansi. Tambahkan include_answer untuk mendapatkan jawaban AI ringkas lengkap dengan sitasi.
Parameter
| Parameter | Tipe | Keterangan |
|---|---|---|
q wajib | string | Kueri pencarian, 2–500 karakter. |
limit | integer | Jumlah hasil, 1–50. Default 10. |
language | string | Kode bahasa, mis. id atau en. Default en. |
topic | string | general (default) atau news. |
time_range | string | day, week, month, atau year. Alias: freshness. |
include_domains | string | Daftar domain dipisah koma; hanya hasil dari domain ini yang dikembalikan. |
exclude_domains | string | Daftar domain dipisah koma yang dikecualikan. |
include_answer | string | basic / true (+1 kredit) atau advanced (+3 kredit, membaca isi halaman sumber). Default tanpa jawaban. |
Contoh permintaan
curl "https://api-ida.arywibowo.id/api/v1/search?q=harga+beras+hari+ini&limit=5&language=id" \
-H "Authorization: Bearer $IDA_API_KEY"import os, requests
r = requests.get(
"https://api-ida.arywibowo.id/api/v1/search",
params={"q": "harga beras hari ini", "limit": 5, "language": "id"},
headers={"Authorization": f"Bearer {os.environ['IDA_API_KEY']}"},
timeout=60,
)
r.raise_for_status()
print(r.json())const params = new URLSearchParams({ q: "harga beras hari ini", limit: "5", language: "id" });
const r = await fetch(`https://api-ida.arywibowo.id/api/v1/search?${params}`, {
headers: { Authorization: `Bearer ${process.env.IDA_API_KEY}` },
});
if (!r.ok) throw new Error((await r.json()).error?.message);
console.log(await r.json());Contoh respons
{
"results": [
{
"title": "Harga Beras Hari Ini Rp16.400/kg (16 Oktober 2026)",
"url": "https://panganindonesia.com/harga/beras",
"snippet": "Harga beras hari ini 16 Oktober 2026: rata-rata nasional Rp 16.400/kg…",
"source": "bing,duckduckgo",
"published_at": "2026-10-16T00:00:00Z",
"retrieved_at": "2026-10-23T06:37:47.644816Z",
"relevance_score": 0.6984
}
],
"cached": false,
"topic": "general",
"usage": {
"credits": 1
}
}Field hasil
| Parameter | Tipe | Keterangan |
|---|---|---|
title | string | Judul halaman. |
url | string | URL sumber. |
snippet | string | Cuplikan teks. |
source | string | Mesin pencari asal. |
published_at | string | null | Tanggal terbit jika diketahui. |
retrieved_at | string | Waktu data diambil. |
relevance_score | number | Skor relevansi 0–1. |
Answer (jawaban AI)
/answer2 kredit (basic) · 4 kredit (advanced)Alias praktis untuk /search dengan include_answer=basic. Menerima parameter yang sama dengan Search. Jawaban memakai penanda sitasi [n] yang merujuk ke citations.
Contoh permintaan
curl "https://api-ida.arywibowo.id/api/v1/answer?q=harga+beras+hari+ini&include_answer=advanced" \
-H "Authorization: Bearer $IDA_API_KEY"import os, requests
r = requests.get(
"https://api-ida.arywibowo.id/api/v1/answer",
params={"q": "harga beras hari ini", "include_answer": "advanced"},
headers={"Authorization": f"Bearer {os.environ['IDA_API_KEY']}"},
timeout=60,
)
r.raise_for_status()
print(r.json())const params = new URLSearchParams({ q: "harga beras hari ini", include_answer: "advanced" });
const r = await fetch(`https://api-ida.arywibowo.id/api/v1/answer?${params}`, {
headers: { Authorization: `Bearer ${process.env.IDA_API_KEY}` },
});
if (!r.ok) throw new Error((await r.json()).error?.message);
console.log(await r.json());Contoh respons
{
"results": [
"…"
],
"cached": true,
"topic": "general",
"answer": "Harga rata-rata nasional beras per 16 Oktober 2026 adalah Rp16.400/kg [1].",
"citations": [
{
"n": 1,
"url": "https://panganindonesia.com/harga/beras",
"title": "Harga Beras Hari Ini Rp16.400/kg (16 Oktober 2026)"
}
],
"answer_meta": {
"depth": "basic",
"model": "ida-mini",
"effective_model": "mini",
"latency_ms": 11683,
"request_id": "5d25897c-6e6b-461a-9daf-08d42484efd3"
},
"usage": {
"credits": 1
}
}"answer": null, answer_error, dan answer_credits_refunded; kredit jawaban dikembalikan dan hasil gagal tidak di-cache. Advanced bisa memakan waktu hingga ~60 detik, jadi gunakan timeout klien yang cukup.Extract
/extract1 kredit per 5 URLMengambil dan membersihkan isi halaman (teks + markdown) dari satu atau beberapa URL. Mendukung render JavaScript dan pemilihan potongan paling relevan terhadap kueri.
Parameter
| Parameter | Tipe | Keterangan |
|---|---|---|
url | string | Satu URL. Isi salah satu dari url atau urls. |
urls | string[] | 1–20 URL. Respons berisi results dan failed_results. |
render_js | boolean | Render halaman dengan browser. Default false. |
query | string | Kueri (2–500 karakter) untuk memilih potongan relevan. |
chunks_per_source | integer | 1–5 potongan relevan per sumber (butuh query). |
max_chars | integer | Potong content/markdown ke 200–200.000 karakter; menandai truncated: true. |
Contoh permintaan
curl -X POST "https://api-ida.arywibowo.id/api/v1/extract" \
-H "Authorization: Bearer $IDA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "max_chars": 2000}'import os, requests
r = requests.post(
"https://api-ida.arywibowo.id/api/v1/extract",
json={
"url": "https://example.com",
"max_chars": 2000
},
headers={"Authorization": f"Bearer {os.environ['IDA_API_KEY']}"},
timeout=120,
)
r.raise_for_status()
print(r.json())const r = await fetch("https://api-ida.arywibowo.id/api/v1/extract", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.IDA_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"url": "https://example.com",
"max_chars": 2000
}),
});
console.log(await r.json());Contoh respons
{
"url": "https://example.com/",
"title": "Example Domain",
"canonical_url": "https://example.com/",
"content": "This domain is for use in documentation examples…",
"markdown": "This domain is for use in documentation examples…",
"metadata": {
"content_length": 900
},
"published_at": null,
"retrieved_at": "2026-10-23T06:38:05.134673Z",
"extraction_method": "playwright+trafilatura",
"content_quality": 0.225,
"warnings": [],
"truncated": true,
"cached": false
}Respons untuk urls
{
"results": [
{
"url": "https://example.com/",
"title": "Example Domain",
"content": "…",
"cached": true
}
],
"failed_results": [
{
"url": "https://contoh.invalid/",
"status": 502,
"reason": "upstream_error",
"upstream_status": null,
"message": "…"
}
],
"usage": {
"credits": 1
}
}Research
/research5 kredit · +4 / +6 dengan synthesizeRiset multi-sumber: mencari, membaca, dan mengekstrak kutipan relevan dari beberapa halaman, lalu menghitung kualitas sumber dan tingkat keyakinan. Opsional: ringkasan AI dengan synthesize.
Parameter
| Parameter | Tipe | Keterangan |
|---|---|---|
query wajib | string | Pertanyaan riset, 2–500 karakter. |
language | string | Kode bahasa. Default en. |
max_sources | integer | 1–20 sumber. Default 8. |
freshness | string | day, week, month, atau year. |
synthesize | boolean | Tambahkan jawaban AI tersintesis. Default false. |
answer_depth | string | basic atau advanced (default) untuk synthesize. |
Contoh permintaan
curl -X POST "https://api-ida.arywibowo.id/api/v1/research" \
-H "Authorization: Bearer $IDA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "inflasi Indonesia 2026", "language": "id", "max_sources": 5}'import os, requests
r = requests.post(
"https://api-ida.arywibowo.id/api/v1/research",
json={
"query": "inflasi Indonesia 2026",
"language": "id",
"max_sources": 5
},
headers={"Authorization": f"Bearer {os.environ['IDA_API_KEY']}"},
timeout=120,
)
r.raise_for_status()
print(r.json())const r = await fetch("https://api-ida.arywibowo.id/api/v1/research", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.IDA_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"query": "inflasi Indonesia 2026",
"language": "id",
"max_sources": 5
}),
});
console.log(await r.json());Contoh respons
{
"query": "inflasi Indonesia 2026",
"sources": [
{
"title": "Inflasi Indonesia (Oktober 2026) — Data & Statistik",
"url": "https://www.statsindo.com/data/ekonomi/inflasi-indonesia/",
"published_at": null,
"retrieved_at": "2026-10-23T06:38:08.287506+00:00",
"source_quality": 0.544,
"relevance_score": 0.6937,
"relevant_excerpts": [
"Inflasi YoY Sep 2026 …"
],
"warnings": []
}
],
"evidence": [
{
"source_url": "https://www.statsindo.com/data/ekonomi/inflasi-indonesia/",
"excerpts": [
"Inflasi YoY Sep 2026 …"
]
}
],
"relevant_excerpts": [
"Inflasi YoY Sep 2026 …"
],
"source_quality": 0.544,
"freshness": null,
"contradictions": [],
"confidence": 0.529,
"warnings": [
"Evidence is extracted from public web sources and has not been independently verified."
],
"generated_at": "2026-10-23T06:38:08.288017+00:00",
"cached": false,
"usage": {
"credits": 5
}
}Chat
/chat/completions1 / 2 / 5 kredit · riset web 8–13Chat dengan model IDA memakai format yang kompatibel dengan OpenAI Chat Completions, jadi SDK OpenAI bisa langsung dipakai dengan mengganti base_url. Opsional: riset web dengan sitasi sumber. Jawaban biasanya selesai dalam 20–30 detik; set timeout klien minimal 180 detik.
chat, yang tidak aktif secara default dan dinyalakan per key lewat switch Chat di halaman API Keys dashboard (owner/admin). Riset web juga butuh scope search. Plan Free mensyaratkan email/telepon terverifikasi. Batas per plan ada di tabel berikut.Batas Chat per plan
| Plan | Konteks | Permintaan/menit | Bersamaan | Chat/hari | Riset web/hari |
|---|---|---|---|---|---|
| Free | 4.000 token | 3 | 1 | 50 | 5 |
| Starter | 8.000 token | 20 | 2 | tanpa batas | 50 |
| Pro | 16.000 token | 60 | 5 | tanpa batas | 300 |
Angka batas dan tarif Chat masih draft dan bisa berubah sebelum peluncuran. Konteks efektif = yang lebih kecil antara konteks model dan konteks plan.
Parameter
| Parameter | Tipe | Keterangan |
|---|---|---|
model | string | Wajib. ID model dari GET /models: ida-chat-fast (cepat & hemat), ida-chat (seimbang), ida-chat-pro (paling kuat). |
messages | object[] | Wajib. Daftar pesan berisi role (system, user, assistant) dan content. Kirim ulang seluruh riwayat setiap giliran (server tidak menyimpan percakapan). |
max_tokens | integer | Batas token jawaban. Default 1024. Total prompt + jawaban dibatasi konteks model dan plan (Free: 4.000 token). Tidak memengaruhi tarif: tier dihitung dari token aktual. |
temperature | number | 0–2. Makin tinggi makin variatif. |
stream | boolean | true untuk respons Server-Sent Events. Default false. |
stream_options.include_usage | boolean | Sertakan usage pada chunk terakhir saat streaming. |
ida.web_search | boolean | object | Riset web + sitasi: true, atau objek dengan depth basic/advanced. Alias: "web": true. Butuh scope chat + search. |
Header opsional X-Request-ID atau Idempotency-Key mencegah permintaan ganda (409 bila dipakai ulang). Daftar model publik tanpa key: GET /api/v1/models. Tiap model memuat context_length dan objek ida: description, web_search (riset web didukung), tiers (nama, batas token, kredit), web_credits, dan placeholder. placeholder: true berarti tarif dan batas masih draft dan bisa berubah. Jangan pakai field ini untuk logika aplikasi.
Biaya per permintaan
| Tier | Total token (prompt + jawaban) | Kredit |
|---|---|---|
short | ≤ 1.000 | 1 |
standard | 1.001–4.000 | 2 |
long | 4.001–16.000 | 5 |
web | riset web aktif, total ≤ 4.000 token | 8 |
web+long | riset web aktif, total > 4.000 token | 13 (8 + 5) |
Tier dihitung dari token aktual setelah jawaban selesai. Error dan jawaban gagal tidak ditagih.
Contoh permintaan
curl -X POST "https://api-ida.arywibowo.id/api/v1/chat/completions" \
-H "Authorization: Bearer $IDA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "ida-chat", "messages": [{"role": "user", "content": "Apa itu IDA Labs?"}], "max_tokens": 512}'import os, requests
r = requests.post(
"https://api-ida.arywibowo.id/api/v1/chat/completions",
json={
"model": "ida-chat",
"messages": [{"role": "user", "content": "Apa itu IDA Labs?"}],
"max_tokens": 512
},
headers={"Authorization": f"Bearer {os.environ['IDA_API_KEY']}"},
timeout=180,
)
r.raise_for_status()
print(r.json()["choices"][0]["message"]["content"])const r = await fetch("https://api-ida.arywibowo.id/api/v1/chat/completions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.IDA_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"model": "ida-chat",
"messages": [{ "role": "user", "content": "Apa itu IDA Labs?" }],
"max_tokens": 512
}),
});
const data = await r.json();
console.log(data.choices[0].message.content);Contoh respons
{
"id": "chatcmpl-…",
"object": "chat.completion",
"created": 1792800000,
"model": "ida-chat",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "IDA Labs adalah platform API pencarian dan AI…",
"ida": { "citations": [] }
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 96,
"total_tokens": 108,
"ida_credits": 1,
"ida_tier": "short"
},
"ida": {
"credits_used": 1,
"tier": "short",
"citations": [],
"request_id": "…"
}
}Streaming (SSE)
Dengan "stream": true respons berupa text/event-stream. Setiap event berbentuk data: {…} berisi choices[0].delta.content. Baris : ping dikirim kira-kira tiap 15 detik agar koneksi tetap hidup (abaikan). Chunk terakhir memuat finish_reason: "stop", ida (kredit, tier, sitasi, credits_remaining) dan usage, lalu data: [DONE]. Error di tengah stream dikirim sebagai data: {"error": {…}} sebelum [DONE].
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","model":"ida-chat","choices":[{"index":0,"delta":{"role":"assistant","content":""}}]}
: ping
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","model":"ida-chat","choices":[{"index":0,"delta":{"content":"IDA Labs adalah…"}}]}
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","model":"ida-chat","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":12,"completion_tokens":96,"total_tokens":108,"ida_credits":1,"ida_tier":"short"},"ida":{"credits_used":1,"tier":"short","citations":[],"request_id":"…","credits_remaining":487}}
data: [DONE]Riset web & sitasi
Kirim "ida": {"web_search": true} agar model mencari di web dulu. Teks jawaban memuat penanda [1], [2] yang merujuk ke daftar sitasi berikut (di choices[0].message.ida.citations dan ida.citations; saat streaming ada di chunk terakhir).
"ida": {
"citations": [
{ "index": 1, "url": "https://contoh.go.id/berita", "title": "Judul sumber", "snippet": "Cuplikan…" }
]
}Pakai SDK OpenAI
Parameter khusus IDA (ida) dikirim lewat extra_body di Python.
# pip install openai
import os
from openai import OpenAI
client = OpenAI(base_url="https://api-ida.arywibowo.id/api/v1", api_key=os.environ["IDA_API_KEY"], timeout=180)
stream = client.chat.completions.create(
model="ida-chat",
messages=[{"role": "user", "content": "Berita ekonomi Indonesia hari ini?"}],
stream=True,
stream_options={"include_usage": True},
extra_body={"ida": {"web_search": True}}, # parameter khusus IDA lewat extra_body
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)// npm i openai
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://api-ida.arywibowo.id/api/v1", apiKey: process.env.IDA_API_KEY, timeout: 180_000 });
const stream = await client.chat.completions.create({
model: "ida-chat",
messages: [{ role: "user", content: "Berita ekonomi Indonesia hari ini?" }],
stream: true,
stream_options: { include_usage: true },
// @ts-expect-error parameter khusus IDA
ida: { web_search: true },
});
for await (const chunk of stream) process.stdout.write(chunk.choices[0]?.delta?.content ?? "");curl -N -X POST "https://api-ida.arywibowo.id/api/v1/chat/completions" \
-H "Authorization: Bearer $IDA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "ida-chat", "messages": [{"role": "user", "content": "Berita ekonomi Indonesia hari ini?"}], "stream": true, "stream_options": {"include_usage": true}, "ida": {"web_search": true}}'Error khusus Chat
| Status | Kode | Arti |
|---|---|---|
| 400 | BAD_REQUEST / CONTEXT_LIMIT | Body tidak valid, atau prompt + max_tokens melebihi konteks model/plan. |
| 401 | UNAUTHORIZED | Key tidak dikirim, salah, atau dicabut. |
| 402 | INSUFFICIENT_CREDITS | Kredit tidak cukup. |
| 403 | SCOPE_FORBIDDEN / VERIFICATION_REQUIRED / CHAT_DISABLED | Key belum punya scope chat (atau search untuk riset web), akun Free belum terverifikasi, atau chat dinonaktifkan. |
| 404 | MODEL_NOT_FOUND | ID model tidak dikenal. Cek GET /models. |
| 409 | DUPLICATE_REQUEST | X-Request-ID/Idempotency-Key yang sama sudah dipakai. |
| 429 | RATE_LIMITED / DAILY_LIMIT / WEB_DAILY_LIMIT / CONCURRENCY_LIMIT / SERVER_BUSY | Batas per menit, harian, riset web harian, jumlah permintaan bersamaan, atau server penuh. Ikuti retry-after. |
| 502–504 | UPSTREAM_ERROR / AUTH_UNAVAILABLE / GROUNDING_UNAVAILABLE / UPSTREAM_TIMEOUT | Gangguan sementara di sisi model atau riset web. Tidak ditagih; coba lagi dengan backoff. |
Images
/images1 kreditPencarian gambar. Mengembalikan URL gambar asli, thumbnail, dan halaman sumber.
Parameter
| Parameter | Tipe | Keterangan |
|---|---|---|
q wajib | string | Kueri, 2–500 karakter. |
limit | integer | 1–30. Default 10. |
language | string | Default all. |
safesearch | integer | 0 (mati), 1 (sedang, default), 2 (ketat). |
Contoh permintaan
curl "https://api-ida.arywibowo.id/api/v1/images?q=candi+borobudur&limit=5" \
-H "Authorization: Bearer $IDA_API_KEY"import os, requests
r = requests.get(
"https://api-ida.arywibowo.id/api/v1/images",
params={"q": "candi borobudur", "limit": 5},
headers={"Authorization": f"Bearer {os.environ['IDA_API_KEY']}"},
timeout=60,
)
r.raise_for_status()
print(r.json())const params = new URLSearchParams({ q: "candi borobudur", limit: "5" });
const r = await fetch(`https://api-ida.arywibowo.id/api/v1/images?${params}`, {
headers: { Authorization: `Bearer ${process.env.IDA_API_KEY}` },
});
if (!r.ok) throw new Error((await r.json()).error?.message);
console.log(await r.json());Contoh respons
{
"results": [
{
"title": "Candi Borobudur",
"image_url": "https://i.pinimg.com/originals/a7/98/20/….jpg",
"thumbnail_url": "https://i.pinimg.com/236x/a7/98/20/….jpg",
"source_url": "https://www.pinterest.com/pin/…",
"source": "pinterest"
}
],
"cached": false
}Crawl
/crawl2 kredit · cek status 1 kreditMenjelajah situs secara asinkron mulai dari satu URL. Respons 202 berisi job_id; pantau dengan GET /crawl/{job_id} dan batalkan dengan DELETE /crawl/{job_id}. Tidak tersedia di plan Free (403 SCOPE_FORBIDDEN).
Parameter
| Parameter | Tipe | Keterangan |
|---|---|---|
start_url wajib | string | URL awal. |
max_pages | integer | 1–200. Default 25. |
max_depth | integer | 0–6. Default 2. |
allowed_domains | string[] | Maks. 20 domain yang boleh dijelajahi. |
Contoh permintaan
curl -X POST "https://api-ida.arywibowo.id/api/v1/crawl" \
-H "Authorization: Bearer $IDA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"start_url": "https://example.com", "max_pages": 10}'import os, requests
r = requests.post(
"https://api-ida.arywibowo.id/api/v1/crawl",
json={
"start_url": "https://example.com",
"max_pages": 10
},
headers={"Authorization": f"Bearer {os.environ['IDA_API_KEY']}"},
timeout=120,
)
r.raise_for_status()
print(r.json())const r = await fetch("https://api-ida.arywibowo.id/api/v1/crawl", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.IDA_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"start_url": "https://example.com",
"max_pages": 10
}),
});
console.log(await r.json());Contoh respons
{
"job_id": "3f1c2a9e-8b7d-4c1e-9a55-2f0d6b1e7c44",
"status": "queued",
"status_url": "/api/v1/crawl/3f1c2a9e-8b7d-4c1e-9a55-2f0d6b1e7c44"
}Health
/healthgratis · tanpa keyCek apakah API hidup. Tidak membutuhkan key dan tidak memakai kredit.
curl https://api-ida.arywibowo.id/api/v1/health{
"status": "ok"
}Header respons
| Header | Tipe | Keterangan |
|---|---|---|
x-ida-credits-remaining | integer | Sisa kredit organisasi setelah permintaan ini (hanya pada respons sukses). |
x-ratelimit-limit | integer | Batas permintaan per menit untuk plan Anda. |
x-ratelimit-remaining | integer | Sisa permintaan pada jendela menit berjalan. |
x-ida-plan | string | Bernilai unlimited untuk akun internal tanpa batas (header rate limit tidak dikirim). |
retry-after | integer | Detik sebelum boleh mencoba lagi (pada 429). |
x-request-id | string | ID unik permintaan. Sertakan saat melapor masalah. |
Kode error
Semua error memakai format yang sama. Field detail disertakan untuk kompatibilitas lama dan sebaiknya tidak dipakai di kode baru.
{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or revoked API key"
}
}| Status | Kode | Arti |
|---|---|---|
| 400 | BAD_REQUEST | Permintaan tidak bisa dibaca (mis. header Content-Length rusak). |
| 401 | UNAUTHORIZED | Key tidak dikirim, salah, atau sudah dicabut. |
| 402 | INSUFFICIENT_CREDITS | Kredit tidak cukup; berisi balance dan required. Tunggu reset bulanan atau upgrade plan. |
| 403 | SCOPE_FORBIDDEN | Plan/key tidak mencakup endpoint ini (mis. crawl di Free). |
| 404 | NOT_FOUND / JOB_NOT_FOUND / UPSTREAM_NOT_FOUND | Route, job crawl, atau halaman sumber (extract) tidak ditemukan. |
| 405 | METHOD_NOT_ALLOWED | Metode HTTP salah untuk endpoint ini. |
| 411 | LENGTH_REQUIRED | Body chunked tidak didukung; kirim Content-Length. |
| 413 | REQUEST_TOO_LARGE / CONTENT_TOO_LARGE | Body lebih dari 1 MiB, atau halaman sumber terlalu besar (extract). |
| 415 | UNSUPPORTED_CONTENT_TYPE | Tipe konten halaman sumber tidak didukung (extract). |
| 422 | VALIDATION_ERROR | Parameter tidak valid, mis. q kurang dari 2 karakter. |
| 429 | RATE_LIMITED | Melebihi batas per menit. Tunggu sesuai retry-after. |
| 502 | UPSTREAM_UNAVAILABLE / UPSTREAM_RESPONSE_TOO_LARGE | Engine tidak bisa dihubungi, atau respons lebih dari 3 MiB. |
| 502 | IMAGE_PROVIDER_UNAVAILABLE / UPSTREAM_BLOCKED / UPSTREAM_ERROR / … | Penyedia gambar atau situs sumber gagal (extract). Berisi url dan upstream_status. |
| 503 | AUTH_UNAVAILABLE | Verifikasi key sementara gagal. Coba lagi dengan backoff. |
| 504 | UPSTREAM_TIMEOUT | Situs sumber tidak merespons tepat waktu (extract). |
Contoh penanganan
import time, requests
def ida_get(path, params, key, retries=3):
for attempt in range(retries):
r = requests.get(f"https://api-ida.arywibowo.id/api/v1/{path}", params=params,
headers={"Authorization": f"Bearer {key}"}, timeout=90)
if r.status_code == 429:
time.sleep(int(r.headers.get("retry-after", "5")))
continue
if r.status_code >= 500:
time.sleep(2 ** attempt)
continue
if not r.ok:
err = r.json().get("error", {})
raise RuntimeError(f"{r.status_code} {err.get('code')}: {err.get('message')}")
return r.json()
raise RuntimeError("IDA API: retries exhausted")async function idaGet(path, params, key, retries = 3) {
for (let attempt = 0; attempt < retries; attempt++) {
const url = `https://api-ida.arywibowo.id/api/v1/${path}?${new URLSearchParams(params)}`;
const r = await fetch(url, { headers: { Authorization: `Bearer ${key}` } });
if (r.status === 429) {
await new Promise((ok) => setTimeout(ok, 1000 * Number(r.headers.get("retry-after") || 5)));
continue;
}
if (r.status >= 500) { await new Promise((ok) => setTimeout(ok, 1000 * 2 ** attempt)); continue; }
const body = await r.json();
if (!r.ok) throw new Error(`${r.status} ${body.error?.code}: ${body.error?.message}`);
return body;
}
throw new Error("IDA API: retries exhausted");
}Rate limit
Batas dihitung per API key per menit (jendela tetap). Melebihi batas menghasilkan 429 RATE_LIMITED dengan header retry-after. Plan Free: 10 permintaan/menit. Lihat tabel harga untuk plan lain.
Kredit & harga
Setiap permintaan memotong kredit dari saldo bulanan organisasi. Kredit bulanan direset setiap awal bulan.
| Operasi | Kredit |
|---|---|
GET /search | 1 |
+ include_answer=basic | +1 |
+ include_answer=advanced | +3 |
GET /images | 1 |
POST /extract | 1 per 5 URL |
POST /research | 5 · dengan synthesize=true: total 9 (answer_depth=basic) / 11 (advanced) |
POST /chat/completions | 1 (≤1k token) · 2 (≤4k) · 5 (≤16k) · riset web 8 (13 bila >4k) |
POST /crawl · GET/DELETE /crawl/{id} | 2 · 1 |
Hasil cache search/research ("cached": true) | biaya dasar gratis |
Hasil cache images/extract | tetap ditagih |
| Respons error (status ≥ 400) | tidak ditagih |
| Jawaban AI gagal / kosong | dikembalikan (refund) |
GET /health | gratis |
Plan
- 500 kredit/bulan
- 10 permintaan/menit
- 1 API key
- Search, answer, extract, research, images
- Chat: 50/hari, 5 riset web/hari, konteks 4.000 token (wajib verifikasi)
- 10.000 kredit/bulan
- 60 permintaan/menit
- 3 API key
- Semua endpoint termasuk crawl
- Chat: konteks 8.000 token, 50 riset web/hari
- 60.000 kredit/bulan
- 200 permintaan/menit
- 10 API key
- Semua endpoint termasuk crawl
- Chat: konteks 16.000 token, 300 riset web/hari
Pembayaran untuk plan berbayar belum dibuka. Harga dapat berubah sebelum peluncuran.
FAQ
Kenapa key saya tidak bisa ditampilkan lagi?
Demi keamanan, server hanya menyimpan hash key. Key lengkap ditampilkan sekali saat dibuat. Jika hilang, gunakan Rotasi untuk membuat key baru.
Apakah saya bisa memanggil API langsung dari browser?
Bisa secara teknis, tetapi key akan terlihat oleh pengguna. Panggil API dari backend Anda dan jangan pernah menaruh key di kode frontend.
Apa bedanya basic dan advanced?
Basic merangkum dari cuplikan hasil pencarian (cepat, +1 kredit). Advanced membaca isi halaman sumber teratas lalu merangkum (lebih akurat, +3 kredit, bisa sampai ~60 detik).
Apakah hasil di-cache?
Ya, hasil identik di-cache sementara. Respons dari cache bertanda cached: true dan biaya dasarnya tidak dipotong.
Bagaimana jika kredit habis?
Permintaan akan ditolak dengan 402 INSUFFICIENT_CREDITS sampai kredit direset awal bulan atau plan di-upgrade.
Apakah API mendukung bahasa Indonesia?
Ya. Gunakan language=id untuk hasil dan jawaban berbahasa Indonesia.
Changelog
- Chat. Endpoint
POST /chat/completions(kompatibel OpenAI, streaming SSE, riset web dengan sitasi) dan mode Chat di Tester dashboard. - Dokumentasi & dashboard baru. Halaman dokumentasi publik, tampilan dashboard diperbarui, tombol salin memakai ikon dan selalu menyalin key lengkap.
- Pendaftaran dibuka dengan verifikasi email. Akun baru otomatis mendapat plan Free (500 kredit/bulan).
- v1 stabil. Format error seragam
{"error":{"code","message"}}, endpoint/answer, jawaban AI gagal tidak ditagih dan tidak di-cache, key yang dicabut langsung ditolak, hasil cache dicatat 0 kredit. - Platform kredit. API key per organisasi, kredit bulanan, rate limit per plan, dan header
x-ida-credits-remaining.