Beranda

Dokumentasi API

Unduh .md

Unggah dokumen dan ambil hasilnya lewat API di paket Bisnis dan Pro. Alamat dasar: https://docbrain.ventera.ai/api/v1.

Kunci API

Pemilik atau admin membuat kunci di Pengaturan, tab API. Teks kunci tampil sekali saat dibuat.

Kunci bisa dibatasi per izin: baca, unggah, review, buka kembali, dan ekspor. Tiga izin terakhir hanya di paket Pro. Cabut kunci kapan saja, dan kunci itu langsung ditolak.

Kirim kunci di header Authorization pada setiap permintaan. Jangan menaruhnya di kode sumber atau aplikasi yang dipakai pengguna akhir.

export DOCBRAIN_KUNCI="dbk_xxxxxxxx_..."

Unggah dokumen: tiga langkah

Langkah 1: daftarkan dokumen. Kirim nama, jenis berkas, dan ukurannya. Jenis dokumen boleh dikosongkan agar AI mendeteksinya.

Berkas yang diterima: PDF sampai 7 MB, serta JPG, PNG, dan WEBP sampai 10 MB. Satu dokumen maksimal 20 halaman.

Permintaan
curl -s -X POST https://docbrain.ventera.ai/api/v1/dokumen \
  -H "Authorization: Bearer $DOCBRAIN_KUNCI" \
  -H "Content-Type: application/json" \
  -d '{"nama_file":"faktur-001.pdf","mime":"application/pdf","ukuran_byte":184233,"jenis":"invoice"}'
Balasan 201
{
  "id": "0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f",
  "unggah": {
    "metode": "PUT",
    "url": "https://.../object/upload/sign/docbrain-dokumen/...?token=...",
    "kepala": { "Content-Type": "application/pdf", "x-upsert": "false" },
    "berlaku_detik": 7200
  },
  "antrekan": "/api/v1/dokumen/0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f/antrekan"
}

Langkah 2: kirim berkasnya ke URL unggah dengan PUT, apa adanya sebagai isi permintaan. URL berlaku dua jam dan hanya untuk satu dokumen.

curl -s -X PUT "<unggah.url dari balasan>" \
  -H "Content-Type: application/pdf" \
  -H "x-upsert: false" \
  --data-binary @faktur-001.pdf

Langkah 3: antrekan dokumen. Hanya kunci yang mendaftarkan dokumen itu yang bisa mengantrekannya.

Permintaan
curl -s -X POST https://docbrain.ventera.ai/api/v1/dokumen/0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f/antrekan \
  -H "Authorization: Bearer $DOCBRAIN_KUNCI"
Balasan 202
{ "id": "0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f", "status": "antre" }

Mengantrekan ulang aman: balasannya sudah_diantrekan. Halaman dihitung ke kuota saat dokumen mulai dibaca, sama seperti unggahan lewat web.

Baca dokumen dan hasilnya

Daftar dokumen organisasi, terbaru dulu. Saring dengan status, atur jumlah dengan batas (1 sampai 100).

Permintaan
curl -s "https://docbrain.ventera.ai/api/v1/dokumen?status=perlu_review&batas=20" \
  -H "Authorization: Bearer $DOCBRAIN_KUNCI"
Balasan 200
{
  "data": [
    {
      "id": "0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f",
      "nama_file": "faktur-001.pdf",
      "mime": "application/pdf",
      "ukuran_byte": 184233,
      "jenis": "invoice",
      "status": "perlu_review",
      "jumlah_halaman": 1,
      "dibuat_pada": "2026-10-09T03:30:00.123456+00:00",
      "selesai_pada": "2026-10-09T03:30:07.000000+00:00",
      "galat": null
    }
  ],
  "berikutnya": "eyJ3IjoiMjAyNi0xMC0wOVQwMzozMDowMC4xMjM0NTYrMDA6MDAiLCJpIjoiMGI4ZjNlN2QtLi4uIn0"
}

Bila berikutnya tidak kosong, kirim nilainya sebagai kursor untuk halaman selanjutnya. Anggap kursor sebagai teks opak.

Detail satu dokumen memuat hasil aktifnya setelah dokumen selesai dibaca. Versi 0 adalah bacaan AI. Versi lebih besar adalah koreksi reviewer.

Organisasi bisa menyalakan persetujuan otomatis per jenis dokumen. Dokumen tanpa satu pun temuan langsung berstatus disetujui, dan bidang disetujui_otomatis bernilai true.

Permintaan
curl -s https://docbrain.ventera.ai/api/v1/dokumen/0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f \
  -H "Authorization: Bearer $DOCBRAIN_KUNCI"
Balasan 200
{
  "id": "0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f",
  "status": "perlu_review",
  "jenis": "invoice",
  "halaman_ditagih": 1,
  "disetujui_otomatis": false,
  "hasil": {
    "versi": 0,
    "jenis": "invoice",
    "data": { "nomor_invoice": "INV-2026-001", "total": 1110000 },
    "temuan": [ { "kode": "total_tidak_cocok", "tingkat": "janggal" } ],
    "tidak_terurai": {}
  }
}

Dokumen yang dihapus atau milik organisasi lain tidak pernah muncul.

Review lewat API (paket Pro)

Kunci dengan izin Review bisa mengoreksi, menyetujui, dan menolak dokumen yang berstatus perlu_review. Izin Buka kembali dipisah, karena setara admin.

Koreksi dulu: ambil detail dokumen, ubah isian di hasil.data, lalu kirim kembali utuh bersama versi dari detail itu. Temuan dihitung ulang oleh DocBrain.

Permintaan
curl -s -X POST https://docbrain.ventera.ai/api/v1/dokumen/0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f/koreksi \
  -H "Authorization: Bearer $DOCBRAIN_KUNCI" \
  -H "Content-Type: application/json" \
  -d '{"versi":0,"data":{ ...hasil.data dari detail, dengan isian yang diperbaiki... }}'
Balasan 200
{ "id": "0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f", "hasil": "disimpan", "versi": 1, "jumlah_janggal": 0 }

Bila versi sudah berubah, balasannya 409 versi_basi. Ambil detail lagi lalu ulangi. Satu dokumen maksimal 50 kali dikoreksi.

Setujui dengan versi terakhir. Dokumen dengan temuan janggal ditolak dengan 409 perlu_konfirmasi, kecuali kamu mengirim terima_janggal: true.

Permintaan
curl -s -X POST https://docbrain.ventera.ai/api/v1/dokumen/0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f/setujui \
  -H "Authorization: Bearer $DOCBRAIN_KUNCI" \
  -H "Content-Type: application/json" \
  -d '{"versi":1}'
Balasan 200
{ "id": "0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f", "status": "disetujui", "jumlah_janggal": 0 }
Balasan 409 untuk dokumen janggal
{ "galat": { "kode": "perlu_konfirmasi", "pesan": "Dokumen punya temuan janggal. Kirim \"terima_janggal\": true untuk tetap menyetujui.", "jumlah_janggal": 1 } }

Tolak wajib menyertakan alasan, maksimal 500 karakter.

curl -s -X POST https://docbrain.ventera.ai/api/v1/dokumen/0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f/tolak \
  -H "Authorization: Bearer $DOCBRAIN_KUNCI" \
  -H "Content-Type: application/json" \
  -d '{"versi":1,"alasan":"Berkas bukan faktur"}'

Buka kembali mengembalikan dokumen yang sudah disetujui atau ditolak ke perlu_review.

curl -s -X POST https://docbrain.ventera.ai/api/v1/dokumen/0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f/buka-kembali \
  -H "Authorization: Bearer $DOCBRAIN_KUNCI"

Koreksi dan keputusan dari kunci API tercatat di jejak audit dengan sumber API dan awalan kunci. Reviewer manusia tetap bisa mengubahnya lewat web.

Ekspor data (paket Pro)

Kunci dengan izin Ekspor mengambil dokumen yang sudah disetujui, urut waktu persetujuan. Jenis wajib. Tanggal (dari, sampai) memakai hari kalender WIB.

Permintaan
curl -s "https://docbrain.ventera.ai/api/v1/ekspor?jenis=invoice&dari=2026-10-01&sampai=2026-10-09&batas=100" \
  -H "Authorization: Bearer $DOCBRAIN_KUNCI"
Balasan 200
{
  "data": [
    {
      "dokumen_id": "0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f",
      "nama_file": "faktur-001.pdf",
      "dibuat_pada": "2026-10-09T03:30:00.123456+00:00",
      "ditinjau_pada": "2026-10-09T04:02:11.000000+00:00",
      "peninjau": "API dbk_ab12cd",
      "versi": 1,
      "janggal_saat_disetujui": 0,
      "data": { "nomor_invoice": "INV-2026-001", "total": 1110000 }
    }
  ],
  "berikutnya": null
}

Bila berikutnya tidak kosong, kirim nilainya sebagai kursor. Satu halaman memuat sampai 200 dokumen.

Format csv memberi satu berkas dengan kolom yang sama seperti ekspor di web, maksimal 5.000 dokumen. Persempit rentang tanggal bila lebih banyak. XLSX dan PDF hanya lewat web.

curl -s "https://docbrain.ventera.ai/api/v1/ekspor?jenis=invoice&format=csv" \
  -H "Authorization: Bearer $DOCBRAIN_KUNCI" -o invoice.csv

Setiap halaman yang dibaca tercatat di audit. Batasnya 100 halaman per jam per kunci.

Webhook (paket Pro)

Webhook memberi tahu sistemmu saat dokumen berubah status, tanpa perlu menanyakannya berulang. Atur di Pengaturan, tab API.

Setiap webhook punya alamat dan rahasia. Rahasia tampil sekali saat dibuat atau diputar. Maksimal 3 webhook per organisasi.

dokumen.terbaca
Hasil bacaan siap. Dokumen menunggu review, kecuali disetujui otomatis.
dokumen.gagal
Dokumen tidak bisa dibaca. Kode galat ada di bidang galat_kode.
dokumen.disetujui
Dokumen disetujui oleh reviewer, lewat API, atau otomatis (data.otomatis true).
dokumen.ditolak
Dokumen ditolak.
dokumen.dibuka_kembali
Dokumen yang sudah diputuskan kembali menunggu review.
webhook.uji
Peristiwa percobaan dari tombol Kirim uji.

Isi pengiriman tidak memuat isi dokumen, nama berkas, atau alasan penolakan. Ambil hasilnya lewat detail dokumen.

Isi (JSON)
{
  "event_id": "5e2c7f0a-3b1d-4c8e-9a6f-1d2e3f4a5b6c",
  "tipe": "dokumen.terbaca",
  "terjadi_pada": "2026-10-09T03:30:07.412Z",
  "data": {
    "dokumen_id": "0b8f3e7d-1c2a-4b5d-9e6f-0a1b2c3d4e5f",
    "status": "perlu_review",
    "jenis": "invoice",
    "jumlah_halaman": 1,
    "versi": 0,
    "otomatis": false,
    "galat_kode": null
  }
}
Header
POST /docbrain/webhook HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: DocBrain-Webhook/1
X-DocBrain-Event: dokumen.terbaca
X-DocBrain-Event-Id: 5e2c7f0a-3b1d-4c8e-9a6f-1d2e3f4a5b6c
X-DocBrain-Timestamp: 1791516607
X-DocBrain-Signature: sha256=9f2c...e41a

Tanda tangan dihitung dari isi mentah: HMAC-SHA256 atas timestamp, titik, lalu isi. Tolak timestamp yang lebih dari 5 menit.

Memeriksa tanda tangan (Node.js)
import { createHmac, timingSafeEqual } from 'node:crypto';

// Pakai isi MENTAH permintaan (sebelum JSON.parse). Rahasia: yang tampil saat webhook dibuat (whsec_...).
export function sahkan(isiMentah, kepala, rahasia) {
  const ts = kepala['x-docbrain-timestamp'];
  const diterima = String(kepala['x-docbrain-signature'] ?? '').replace(/^sha256=/, '');
  if (!/^\d{9,12}$/.test(ts ?? '')) return false;
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // tolak yang lebih dari 5 menit
  const hitung = createHmac('sha256', rahasia).update(`${ts}.${isiMentah}`).digest('hex');
  const a = Buffer.from(diterima, 'hex');
  const b = Buffer.from(hitung, 'hex');
  return a.length === b.length && timingSafeEqual(a, b);
}

// Balas 2xx secepatnya, lalu proses. Simpan event_id untuk membuang pengiriman ganda.
app.post('/docbrain/webhook', express.raw({ type: '*/*' }), (req, res) => {
  const isi = req.body.toString('utf8');
  if (!sahkan(isi, req.headers, process.env.DOCBRAIN_WEBHOOK_RAHASIA)) return res.sendStatus(401);
  const peristiwa = JSON.parse(isi);
  res.sendStatus(204);
  // ... ambil hasilnya: GET /api/v1/dokumen/{peristiwa.data.dokumen_id}
});

Alamat penerima harus https di port 443 dengan nama domain publik. Alamat IP dan jaringan lokal ditolak. Pengalihan tidak diikuti.

Balas 2xx dalam 10 detik. Balasan lain dianggap gagal dan dicoba lagi setelah 1 menit, 10 menit, 1 jam, 6 jam, lalu 24 jam.

Setelah percobaan keenam, pengiriman ditandai gagal. Dua puluh kegagalan beruntun mematikan webhook itu, dihitung sekali per 10 menit. Aktifkan lagi setelah penerima pulih.

Pengiriman bisa datang ganda dan tidak selalu berurutan. Pakai event_id untuk membuang ganda, dan ambil status terbaru dari detail dokumen.

Pengiriman digerakkan oleh aktivitas dan penjadwal harian, jadi percobaan ulang bisa tertunda. Cocokkan dengan daftar dokumen secara berkala.

Tombol Kirim uji mengirim peristiwa webhook.uji. Pengiriman yang gagal bisa dikirim ulang dari daftar pengiriman.

Status dokumen

antre
Berkas diterima dan menunggu giliran dibaca.
diproses
AI sedang membaca dokumen.
perlu_review
Hasil siap. Ada hal yang perlu dilihat reviewer sebelum disetujui.
disetujui
Reviewer sudah menyetujui hasilnya, atau DocBrain menyetujuinya otomatis (disetujui_otomatis true).
ditolak
Reviewer menolak dokumen ini.
gagal
Dokumen tidak bisa dibaca. Lihat kode dan pesan di bidang galat.

Tanyakan status secara berkala, misalnya tiap 5 sampai 10 detik. Satu dokumen biasanya selesai dalam hitungan detik.

Galat dan batas

Galat selalu berbentuk JSON dengan kode yang bisa diproses program.

{ "galat": { "kode": "kuota_habis", "pesan": "Kuota halaman bulan ini sudah habis." } }
StatusKodeArti
401kunci_tidak_sahKunci salah, dicabut, atau organisasi tidak berlangganan paket dengan API.
403izin_ditolakKunci tidak punya izin untuk tindakan itu.
403kuota_habisKuota halaman bulan ini habis.
403langganan_tidak_aktifLangganan organisasi tidak aktif.
400masukan_tidak_sahIsian permintaan salah. Pesannya menyebut isian yang bermasalah.
404tidak_ditemukanDokumen tidak ada, milik organisasi lain, atau sudah dihapus.
409berkas_belum_adaBerkas belum diunggah ke URL unggah.
409versi_basiVersi data sudah berubah. Ambil detail dokumen lagi.
409bukan_perlu_reviewDokumen tidak sedang menunggu review.
409perlu_konfirmasiDokumen punya temuan janggal. Kirim terima_janggal: true untuk menyetujui.
409bukan_keputusanDokumen belum disetujui atau ditolak, jadi tidak bisa dibuka kembali.
409batas_versiDokumen sudah 50 kali dikoreksi.
422tanpa_hasilDokumen belum punya hasil bacaan.
429batas_eksporBatas 100 halaman ekspor per jam tercapai.
413terlalu_besarIsi permintaan terlalu besar. Kirim hanya metadata.
422mime_tidak_cocokJenis berkas yang terunggah berbeda dari yang didaftarkan.
422berkas_kosongBerkas yang terunggah kosong.
422berkas_terlalu_besarBerkas melewati batas ukuran.
429terlalu_banyak_permintaanLebih dari 120 permintaan dalam semenit. Tunggu sesuai Retry-After.
429batas_harianBatas 200 unggahan per hari untuk kunci ini tercapai.
429batas_harian_organisasiBatas 1.000 unggahan per hari untuk organisasi tercapai.
429terlalu_banyak_menungguTerlalu banyak dokumen yang belum selesai diunggah.
500galat_serverGalat di sisi DocBrain. Coba lagi nanti.
  • 120 permintaan per menit per kunci.
  • 200 unggahan per hari per kunci, dan 1.000 per hari per organisasi.
  • Maksimal 50 dokumen yang belum selesai diunggah per kunci.
  • Unggahan memakai kuota halaman organisasi, sama seperti lewat web.

Contoh lengkap (JavaScript)

const kunci = process.env.DOCBRAIN_KUNCI;
const kepala = { Authorization: `Bearer ${kunci}`, 'Content-Type': 'application/json' };

// 1. Daftarkan dokumen dan dapatkan URL unggah.
const dibuat = await fetch('https://docbrain.ventera.ai/api/v1/dokumen', {
  method: 'POST',
  headers: kepala,
  body: JSON.stringify({ nama_file: berkas.name, mime: berkas.type, ukuran_byte: berkas.size }),
}).then((r) => r.json());

// 2. Unggah berkasnya apa adanya ke URL itu.
await fetch(dibuat.unggah.url, { method: 'PUT', headers: dibuat.unggah.kepala, body: berkas });

// 3. Antrekan, lalu tanya hasilnya sampai selesai.
await fetch('https://docbrain.ventera.ai' + dibuat.antrekan, { method: 'POST', headers: kepala });
const hasil = await fetch('https://docbrain.ventera.ai/api/v1/dokumen/' + dibuat.id, { headers: kepala }).then((r) => r.json());

Keamanan

  • DocBrain menyimpan hash kunci, bukan kuncinya. Kunci yang hilang tidak bisa dipulihkan: buat yang baru.
  • Setiap kunci hanya melihat dokumen organisasinya sendiri. Kunci tetap berlaku sampai dicabut, juga bila pembuatnya keluar dari organisasi.
  • Unggahan, bacaan hasil, dan pencabutan kunci tercatat di jejak audit organisasi, tanpa isi dokumen.
  • Izin review, buka kembali, dan ekspor hanya untuk paket Pro. Bila paket turun, kunci itu berhenti bekerja tanpa dicabut.
  • Webhook ditandatangani dengan rahasia per webhook. Putar rahasia bila bocor; yang lama langsung tidak berlaku.

Butuh bantuan? Hubungi tim Ventera melalui ventera.ai.