IDALabs Docs Masuk
Dokumentasi API · v1

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

  1. 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.
  2. Simpan key sebagai environment variable. Jangan menaruh key di kode frontend atau repo publik.
Shell
export IDA_API_KEY="<API_KEY>"  # ganti dengan key Anda (ida_live_...)
  1. 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"

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.

Header
Authorization: Bearer ida_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# atau
x-api-key: ida_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Jaga kerahasiaan key. Server hanya menyimpan hash key, jadi key yang hilang tidak bisa ditampilkan lagi. Gunakan Rotasi di dashboard untuk membuat key baru. Key yang dicabut langsung ditolak (401) dalam hitungan detik.

Jumlah 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

Base URL
https://api-ida.arywibowo.id/api/v1
  • Semua respons berformat JSON (UTF-8). Body POST harus Content-Type: application/json dengan header Content-Length (chunked tidak didukung), maksimal 1 MB.
  • Waktu dalam ISO 8601 UTC. Kirim header x-request-id sendiri jika ingin melacak permintaan; jika tidak, server membuatkannya.
  • Hasil yang identik di-cache sementara. Respons dari cache ditandai "cached": true dan biaya dasarnya gratis.

Answer (jawaban AI)

GET/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"

Contoh respons

JSON
{
  "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
  }
}
Jawaban gagal tidak ditagih. Jika model tidak menghasilkan jawaban (mis. timeout), respons berisi "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

POST/extract1 kredit per 5 URL

Mengambil dan membersihkan isi halaman (teks + markdown) dari satu atau beberapa URL. Mendukung render JavaScript dan pemilihan potongan paling relevan terhadap kueri.

Parameter

ParameterTipeKeterangan
urlstringSatu URL. Isi salah satu dari url atau urls.
urlsstring[]1–20 URL. Respons berisi results dan failed_results.
render_jsbooleanRender halaman dengan browser. Default false.
querystringKueri (2–500 karakter) untuk memilih potongan relevan.
chunks_per_sourceinteger1–5 potongan relevan per sumber (butuh query).
max_charsintegerPotong 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}'

Contoh respons

JSON
{
  "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

JSON
{
  "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

POST/research5 kredit · +4 / +6 dengan synthesize

Riset multi-sumber: mencari, membaca, dan mengekstrak kutipan relevan dari beberapa halaman, lalu menghitung kualitas sumber dan tingkat keyakinan. Opsional: ringkasan AI dengan synthesize.

Parameter

ParameterTipeKeterangan
query wajibstringPertanyaan riset, 2–500 karakter.
languagestringKode bahasa. Default en.
max_sourcesinteger1–20 sumber. Default 8.
freshnessstringday, week, month, atau year.
synthesizebooleanTambahkan jawaban AI tersintesis. Default false.
answer_depthstringbasic 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}'

Contoh respons

JSON
{
  "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

POST/chat/completions1 / 2 / 5 kredit · riset web 8–13

Chat 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 tersedia di semua plan, termasuk Free. Key perlu scope 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

PlanKonteksPermintaan/menitBersamaanChat/hariRiset web/hari
Free4.000 token31505
Starter8.000 token202tanpa batas50
Pro16.000 token605tanpa batas300

Angka batas dan tarif Chat masih draft dan bisa berubah sebelum peluncuran. Konteks efektif = yang lebih kecil antara konteks model dan konteks plan.

Parameter

ParameterTipeKeterangan
modelstringWajib. ID model dari GET /models: ida-chat-fast (cepat & hemat), ida-chat (seimbang), ida-chat-pro (paling kuat).
messagesobject[]Wajib. Daftar pesan berisi role (system, user, assistant) dan content. Kirim ulang seluruh riwayat setiap giliran (server tidak menyimpan percakapan).
max_tokensintegerBatas token jawaban. Default 1024. Total prompt + jawaban dibatasi konteks model dan plan (Free: 4.000 token). Tidak memengaruhi tarif: tier dihitung dari token aktual.
temperaturenumber0–2. Makin tinggi makin variatif.
streambooleantrue untuk respons Server-Sent Events. Default false.
stream_options.include_usagebooleanSertakan usage pada chunk terakhir saat streaming.
ida.web_searchboolean | objectRiset 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

TierTotal token (prompt + jawaban)Kredit
short≤ 1.0001
standard1.001–4.0002
long4.001–16.0005
webriset web aktif, total ≤ 4.000 token8
web+longriset web aktif, total > 4.000 token13 (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}'

Contoh respons

JSON
{
  "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].

SSE
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).

JSON
"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)

Error khusus Chat

StatusKodeArti
400BAD_REQUEST / CONTEXT_LIMITBody tidak valid, atau prompt + max_tokens melebihi konteks model/plan.
401UNAUTHORIZEDKey tidak dikirim, salah, atau dicabut.
402INSUFFICIENT_CREDITSKredit tidak cukup.
403SCOPE_FORBIDDEN / VERIFICATION_REQUIRED / CHAT_DISABLEDKey belum punya scope chat (atau search untuk riset web), akun Free belum terverifikasi, atau chat dinonaktifkan.
404MODEL_NOT_FOUNDID model tidak dikenal. Cek GET /models.
409DUPLICATE_REQUESTX-Request-ID/Idempotency-Key yang sama sudah dipakai.
429RATE_LIMITED / DAILY_LIMIT / WEB_DAILY_LIMIT / CONCURRENCY_LIMIT / SERVER_BUSYBatas per menit, harian, riset web harian, jumlah permintaan bersamaan, atau server penuh. Ikuti retry-after.
502–504UPSTREAM_ERROR / AUTH_UNAVAILABLE / GROUNDING_UNAVAILABLE / UPSTREAM_TIMEOUTGangguan sementara di sisi model atau riset web. Tidak ditagih; coba lagi dengan backoff.

Coba di Tester →

Images

GET/images1 kredit

Pencarian gambar. Mengembalikan URL gambar asli, thumbnail, dan halaman sumber.

Parameter

ParameterTipeKeterangan
q wajibstringKueri, 2–500 karakter.
limitinteger1–30. Default 10.
languagestringDefault all.
safesearchinteger0 (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"

Contoh respons

JSON
{
  "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

POST/crawl2 kredit · cek status 1 kredit

Menjelajah 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

ParameterTipeKeterangan
start_url wajibstringURL awal.
max_pagesinteger1–200. Default 25.
max_depthinteger0–6. Default 2.
allowed_domainsstring[]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}'

Contoh respons

JSON
{
  "job_id": "3f1c2a9e-8b7d-4c1e-9a55-2f0d6b1e7c44",
  "status": "queued",
  "status_url": "/api/v1/crawl/3f1c2a9e-8b7d-4c1e-9a55-2f0d6b1e7c44"
}

Health

GET/healthgratis · tanpa key

Cek apakah API hidup. Tidak membutuhkan key dan tidak memakai kredit.

cURL
curl https://api-ida.arywibowo.id/api/v1/health
JSON
{
  "status": "ok"
}

Header respons

HeaderTipeKeterangan
x-ida-credits-remainingintegerSisa kredit organisasi setelah permintaan ini (hanya pada respons sukses).
x-ratelimit-limitintegerBatas permintaan per menit untuk plan Anda.
x-ratelimit-remainingintegerSisa permintaan pada jendela menit berjalan.
x-ida-planstringBernilai unlimited untuk akun internal tanpa batas (header rate limit tidak dikirim).
retry-afterintegerDetik sebelum boleh mencoba lagi (pada 429).
x-request-idstringID 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.

JSON
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or revoked API key"
  }
}
StatusKodeArti
400BAD_REQUESTPermintaan tidak bisa dibaca (mis. header Content-Length rusak).
401UNAUTHORIZEDKey tidak dikirim, salah, atau sudah dicabut.
402INSUFFICIENT_CREDITSKredit tidak cukup; berisi balance dan required. Tunggu reset bulanan atau upgrade plan.
403SCOPE_FORBIDDENPlan/key tidak mencakup endpoint ini (mis. crawl di Free).
404NOT_FOUND / JOB_NOT_FOUND / UPSTREAM_NOT_FOUNDRoute, job crawl, atau halaman sumber (extract) tidak ditemukan.
405METHOD_NOT_ALLOWEDMetode HTTP salah untuk endpoint ini.
411LENGTH_REQUIREDBody chunked tidak didukung; kirim Content-Length.
413REQUEST_TOO_LARGE / CONTENT_TOO_LARGEBody lebih dari 1 MiB, atau halaman sumber terlalu besar (extract).
415UNSUPPORTED_CONTENT_TYPETipe konten halaman sumber tidak didukung (extract).
422VALIDATION_ERRORParameter tidak valid, mis. q kurang dari 2 karakter.
429RATE_LIMITEDMelebihi batas per menit. Tunggu sesuai retry-after.
502UPSTREAM_UNAVAILABLE / UPSTREAM_RESPONSE_TOO_LARGEEngine tidak bisa dihubungi, atau respons lebih dari 3 MiB.
502IMAGE_PROVIDER_UNAVAILABLE / UPSTREAM_BLOCKED / UPSTREAM_ERROR / …Penyedia gambar atau situs sumber gagal (extract). Berisi url dan upstream_status.
503AUTH_UNAVAILABLEVerifikasi key sementara gagal. Coba lagi dengan backoff.
504UPSTREAM_TIMEOUTSitus 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")

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.

Tips: simpan hasil di sisi Anda, pakai ulang kueri yang sama (hasil cache gratis), dan gunakan backoff saat menerima 429 atau 5xx.

Kredit & harga

Setiap permintaan memotong kredit dari saldo bulanan organisasi. Kredit bulanan direset setiap awal bulan.

OperasiKredit
GET /search1
+ include_answer=basic+1
+ include_answer=advanced+3
GET /images1
POST /extract1 per 5 URL
POST /research5 · dengan synthesize=true: total 9 (answer_depth=basic) / 11 (advanced)
POST /chat/completions1 (≤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/extracttetap ditagih
Respons error (status ≥ 400)tidak ditagih
Jawaban AI gagal / kosongdikembalikan (refund)
GET /healthgratis

Plan

Free
Gratis
  • 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)
StarterSegera · harga placeholder
Rp20.000/bln
  • 10.000 kredit/bulan
  • 60 permintaan/menit
  • 3 API key
  • Semua endpoint termasuk crawl
  • Chat: konteks 8.000 token, 50 riset web/hari
ProSegera · harga placeholder
Rp50.000/bln
  • 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

  1. Chat. Endpoint POST /chat/completions (kompatibel OpenAI, streaming SSE, riset web dengan sitasi) dan mode Chat di Tester dashboard.
  2. Dokumentasi & dashboard baru. Halaman dokumentasi publik, tampilan dashboard diperbarui, tombol salin memakai ikon dan selalu menyalin key lengkap.
  3. Pendaftaran dibuka dengan verifikasi email. Akun baru otomatis mendapat plan Free (500 kredit/bulan).
  4. 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.
  5. Platform kredit. API key per organisasi, kredit bulanan, rate limit per plan, dan header x-ida-credits-remaining.