Lewati ke konten

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

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

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.

Terminal window
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.

Terminal window
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.

Terminal window
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 lain
Terminal window
# 1. edit (revisi saat ini = 1)
curl -X PATCH .../v1/internal/product-drafts/$ID -d '{"expectedRevision":1,"brand":"Merek Baru"}' ...
# 2. submit
curl -X POST .../v1/internal/product-drafts/$ID/submit -d '{}' ...
# 3. publish
curl -X POST .../v1/internal/product-drafts/$ID/review -d '{"decision":"approve"}' ...
Terminal window
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 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.