Endpoint dataset
Basis URL: https://navint-api-v01.navvigasi.workers.dev. Semua endpoint (kecuali /v1/dataset/login) membutuhkan Authorization: Bearer <token sesi dataset>; endpoint pengelolaan pengguna memakai admin token.
| Endpoint | Fungsi |
|---|---|
POST /v1/dataset/login |
Login dengan email terdaftar (tanpa token). Body { email } → { token, actorId, email, role }, sesi 7 hari |
GET /v1/dataset/users |
Daftar pengguna dataset. Hanya admin token |
PUT /v1/dataset/users/:email |
Tambah/ubah pengguna { role, active? }. Hanya admin token |
POST /v1/session |
Jalur lama untuk lead: buat sesi dengan admin token ({ email, role }) |
GET /v1/internal/product-drafts |
100 draft terbaru |
GET /v1/internal/product-drafts/:id |
Satu draft |
POST /v1/internal/product-drafts |
Buat draft |
PATCH /v1/internal/product-drafts/:id |
Edit draft. Wajib expectedRevision. Draft terbit tidak bisa diubah (409) |
POST /v1/internal/product-drafts/:id/photos |
Tambah foto (jumlah bebas, maks 30). multipart/form-data: image (JPEG/PNG/WebP, maks 8 MB), side opsional (label: depan, belakang, kiri, kanan, atas, bawah, tutup, segel, dasar, kode_cetak, daur_ulang, karton_luar, karton_terbuka, penampang, komponen, skala, lainnya; bawaan lainnya; boleh berulang), note opsional. Berkas identik tidak digandakan (duplicate: true) |
GET /v1/internal/product-drafts/:id/photos |
Daftar foto draft: id, side (label), note, mime, bytes, sha256, createdAt |
PATCH /v1/internal/product-drafts/:id/photos/:photoId |
Ganti label/catatan: { side?, note? } |
DELETE /v1/internal/product-drafts/:id/photos/:photoId |
Lepas satu foto (sebelum terbit) |
POST /v1/internal/product-drafts/:id/extract |
Membaca foto draft dengan model vision dan mengembalikan usulan isian (proposal, uncertain, warnings, model, usage, sides, missingSides). Tidak mengubah draft. 503 bila kunci belum dipasang, 429 bila melebihi 20/jam |
GET/POST /v1/internal/product-drafts/:id/media, DELETE .../media/:mediaId, GET /v1/internal/media/:mediaId |
Media tambahan draft: foto detail bertipe dan dokumen. multipart: kind (foto/dokumen), type, file, note?. Lihat Data Packaging Intelligence |
GET /v1/internal/photos/:photoId |
Mengambil berkas foto (stream dari R2) |
POST /v1/internal/product-drafts/:id/submit |
Kirim ke review |
POST /v1/internal/product-drafts/:id/review |
{ decision: "approve" | "reject" | "request_changes" } |
GET /v1/catalog/products |
Products terbit dengan pencarian, filter, urutan, dan paginasi (lihat Parameter daftar Products di bawah) |
GET /v1/catalog/products/:id |
Satu produk: alias, kategori, details, misc, miscNote, foto |
PATCH /v1/catalog/products/:id |
Sunting produk terbit. Wajib expectedRevision; menerima semua field draft + categoryId + aliases (mengganti seluruh daftar). Keadaan sebelumnya direkam sebagai revisi. 409 bila revisi basi atau GTIN dipakai produk lain |
GET /v1/catalog/products/:id/revisions |
Riwayat suntingan (terbaru dulu) |
GET /v1/catalog/products/:id/photos, POST .../photos, PATCH .../photos/:photoId, DELETE .../photos/:photoId |
Lihat, tambah, ganti label, dan lepas foto produk terbit (sama seperti draft) |
GET /v1/catalog/products/:id/variants |
Varian jumlah produk satuan ini |
POST /v1/catalog/products/:id/variants |
Tambah varian jumlah { packLabel, containedQty, gtin14?, name? }. packLabel: renceng, pak, inner, dus, karton, bundle, paket, lainnya; containedQty bilangan bulat 2–10.000. Varian = produk katalog tersendiri dengan containedProductId, containedQty, packLabel; isi bersih total dihitung otomatis. 409 bila kombinasi ganda atau GTIN bentrok; 422 bila induk adalah varian |
DELETE /v1/catalog/products/:id/variants/:variantId |
Arsipkan varian (disembunyikan dari katalog) |
POST /v1/catalog/products/:id/extract |
Baca ulang foto produk terbit menjadi usulan isian (tidak mengubah produk) |
GET/POST /v1/catalog/products/:id/media, DELETE .../media/:mediaId, GET /v1/catalog/media/:mediaId |
Media tambahan produk terbit (sama seperti draft). Detail produk dan draft juga mengembalikan readiness per fase |
GET /v1/catalog/categories |
Pohon kategori dua tingkat + jumlah produk + uncategorized |
POST /v1/catalog/categories |
Tambah kategori { name, parentId?, externalRefs? } (maks dua tingkat; nama unik per induk) |
PATCH /v1/catalog/categories/:id |
Sunting name, parentId (pindah induk), sortOrder, externalRefs ({ bpom, openFoodFacts, other }) |
POST /v1/catalog/categories/reorder |
{ parentId, ids: [...] } menetapkan urutan saudara kandung |
DELETE /v1/catalog/categories/:id?moveTo=ID|none |
Hapus kategori tanpa subkategori; bila dipakai produk, moveTo wajib (id kategori lain atau none) dan produk dipindahkan |
GET /v1/catalog/photos/:photoId |
Berkas foto produk terbit |
Jalur data menu
Section titled “Jalur data menu”Semua di bawah /v1/internal/menu (operator/reviewer). {jenis} = dishes, modifier-groups, sources, source-items.
| Endpoint | Fungsi |
|---|---|
GET /v1/internal/menu/{jenis}?q=&status=&family=&parentId=&linkId=&missing=&sort=&limit=&offset= |
Daftar dengan pencarian (nama + sebutan), filter, facets (keluarga dan status), dan total. missing: alias, modifier, unverified, unlinked, noprice, noparent |
POST /v1/internal/menu/{jenis} |
Buat entri (status draft; sources langsung published). 409 bila nama sudah ada. Hidangan mengembalikan warnings untuk sebutan yang sama dengan hidangan lain |
GET/PATCH /v1/internal/menu/{jenis}/:id |
Baca atau sunting (PATCH wajib expectedRevision) |
POST .../:id/submit, POST .../:id/review |
Kirim ke review; { decision: "approve" | "reject" | "request_changes" } (tidak untuk sources) |
DELETE .../:id |
Hapus entri yang belum terbit dan tidak dirujuk |
GET/POST /v1/internal/menu/sources/:id/media, DELETE .../media/:mediaId |
Foto menu sumber (multipart: kind=foto, type=menu, file). Berkasnya lewat GET /v1/internal/media/:mediaId |
POST /v1/internal/menu/sources/:id/extract |
Baca foto menu sumber (maks 6) menjadi usulan item: proposal.items[] (displayName, section, priceText, priceIdr, variants[], dietary[], uncertain, dish = saran hidangan kanonik), warnings, model, usage. Tidak menyimpan apa pun. 503 tanpa kunci, 422 tanpa foto, 429 di atas 20/jam |
POST /v1/internal/menu/source-items/bulk |
{ sourceId, items: [...] } (1–100). Menyimpan massal sebagai draft; atomik (422 dengan details.errors[{index,message}] bila ada yang tidak valid); nama yang sudah ada di sumber dilewati (skipped) |
GET /v1/internal/menu/stats |
Jumlah per jenis/status dan antrean kerja |
GET /v1/menu-ontology/dishes?q=&family= |
Baca-saja: hidangan kanonik terbit |
GET /v1/menu-ontology/modifier-groups |
Baca-saja: grup modifier terbit |
POST /v1/menu-ontology/match |
{ text } → { status: "matched" | "clarify" | "not_found", best?, candidates[] } dengan skor dan cara cocok |
Parameter daftar Products
Section titled “Parameter daftar Products”GET /v1/catalog/products (semua opsional):
| Parameter | Arti |
|---|---|
q |
Pencarian. Setiap kata harus cocok di nama, merek, varian, varian penyebutan nama, atau GTIN (angka ≥ 4 digit) |
category |
Id kategori; kategori induk mencakup anaknya. none = tanpa kategori |
brand |
Merek (tanpa huruf besar/kecil), pisahkan koma untuk beberapa |
packageFamily |
Bentuk kemasan, pisahkan koma |
missing |
Filter kekurangan, pisahkan koma: photo, photos2 (kurang dari 2 foto), details, gtin, category, brand |
variants |
hide (sembunyikan varian jumlah), only (hanya varian), atau kosong (semua) |
sort |
name, -name, brand, created, -created, updated, -updated (bawaan: relevansi bila ada q, selain itu name) |
limit, offset |
Paginasi (limit maks 50, offset maks 100000) |
facets=1 |
Sertakan hitungan merek (30 teratas), kemasan, dan jumlah per kategori sesuai filter lain |
Respons: { items, total, offset, limit, hasMore, facets? }. Tiap item memuat categoryId, categoryName, photoCount, thumbPhotoId (foto depan, atau foto pertama), variantCount, packLabel, containedQty, containedProductId, dan hasDetails.
Contoh: buat draft
Section titled “Contoh: buat draft”curl -X POST https://navint-api-v01.navvigasi.workers.dev/v1/internal/product-drafts \ -H "authorization: Bearer $TOKEN_SESI" -H "content-type: application/json" \ -d '{ "name": "Susu UHT Cokelat 250 mL", "brand": "ContohMerek", "variant": "cokelat", "gtin14": "8991234567891", "netContent": { "value": 250, "unit": "MLT" }, "packageFamily": "carton", "tradeItemLevel": "each", "aliases": ["susu coklat", "choco milk"], "notes": "Sumber: foto kemasan 22 Okt" }'Respons 201: { "data": { "id": "...", "status": "draft", "revision": 1, "payload": { ... } } }.
Contoh: draft dengan detail, data tambahan, dan varian nama
Section titled “Contoh: draft dengan detail, data tambahan, dan varian nama”details memakai struktur di Kamus field. misc adalah daftar { key, value }, miscNote teks bebas.
curl -X POST .../v1/internal/product-drafts \ -H "authorization: Bearer $TOKEN_SESI" -H "content-type: application/json" \ -d '{ "name": "Indomie Mi Goreng", "brand": "Indomie", "aliases": ["indomie goreng", "mi goreng indomie"], "netContent": { "value": 85, "unit": "GRM" }, "details": { "ingredients": { "text": "Tepung terigu, minyak nabati, ...", "contains": ["telur", "susu"] }, "nutrition": { "basis": "per_serving", "energyTotalKcal": 400, "rows": [{ "label": "Lemak total", "amount": 16, "unit": "g", "akgPercent": 24 }] }, "manufacturer": { "producedBy": "PT Indofood CBP Sukses Makmur Tbk", "country": "Indonesia" } }, "misc": [{ "key": "slogan", "value": "Indomie Seleraku" }], "miscNote": "Nomor BPOM belum diverifikasi." }'Satuan atau pilihan yang tidak dikenal ditolak dengan 400 dan pesan berbahasa Indonesia.
Contoh: unggah foto
Section titled “Contoh: unggah foto”curl -X POST .../v1/internal/product-drafts/$ID/photos \ -H "authorization: Bearer $TOKEN_SESI" \ -F side=depan -F image=@depan.jpg # side opsional; ulangi untuk foto lainContoh: edit lalu submit lalu publish
Section titled “Contoh: edit lalu submit lalu publish”# 1. edit (revisi saat ini = 1)curl -X PATCH .../v1/internal/product-drafts/$ID -d '{"expectedRevision":1,"brand":"Merek Baru"}' ...# 2. submitcurl -X POST .../v1/internal/product-drafts/$ID/submit -d '{}' ...# 3. publishcurl -X POST .../v1/internal/product-drafts/$ID/review -d '{"decision":"approve"}' ...Mencari duplikat sebelum membuat draft
Section titled “Mencari duplikat sebelum membuat draft”curl ".../v1/catalog/products?q=susu%20cokelat&limit=50" -H "authorization: Bearer $TOKEN_SESI"curl ".../v1/catalog/products?gtin=8991234567891" -H "authorization: Bearer $TOKEN_SESI"Respons: { "data": { "items": [ ... ], "hasMore": false } }.
Alamat API
Section titled “Alamat API”| Alamat | Status |
|---|---|
https://navint-api-v01.navvigasi.workers.dev |
Dipakai untuk pekerjaan baru |
https://navint-dataset-v01.navvigasi.workers.dev |
Masih aktif, kode dan data sama |
https://navv-ci-core.navvigasi.workers.dev |
Masih aktif tetapi tidak lagi dipakai aplikasi mana pun |
Ketiganya berjalan dari kode yang sama dan berbagi satu database (D1) dan satu bucket foto (R2). Aplikasi Smash POS (Retail, F&B, Self-order, Backoffice) memakai navint-api-v01. Secret ORDER_QR_SECRET sama pada navint-api-v01 dan navint-dataset-v01, tetapi berbeda pada navv-ci-core; QR meja yang dicetak dari navv-ci-core tidak berlaku di dua alamat lainnya.