Berkas Form BPMN untuk Integrasi Pihak Ketiga
Apa yang diterima sistem luar (LOS, core banking, dan sejenisnya) ketika sebuah proses mengirim berkas dari form BPMN — isi placeholder variabel berkas sebelum dan sesudah rilis 2026.9.4, format metadata, dan API lampiran form.
Gambaran Umum
Field File Upload pada form BPMN menghasilkan sebuah berkas lampiran yang disimpan di object storage. Ketika Service Task (API Call atau addon) mengirim berkas itu ke sistem luar, yang dikirim berubah mulai rilis 2026.9.4:
| Sebelum 2026.9.4 | Sesudah 2026.9.4 | |
|---|---|---|
Isi placeholder ${namaVariabelBerkas} di body integrasi | Isi berkas dalam base64 | URL unduh bertanda tangan, sekali pakai |
| Yang disimpan di variabel proses | Berkas biner (tipe File) | String JSON metadata (attachment_id, file_name, mime_type, size) |
| Penerima perlu | Men-decode base64 | Mengunduh berkas dari URL, segera |
Ini adalah breaking change bagi penerima yang selama ini men-decode base64 dari field tersebut. Kode penerima yang tidak diubah akan mencoba men-decode sebuah URL sebagai base64. Baca bagian Membedakan URL dan base64 untuk cara membuat penerima menerima keduanya selama masa transisi.
Isi Placeholder Variabel Berkas di Body Integrasi
Di konfigurasi API Call maupun payload addon, berkas dirujuk lewat placeholder ${namaVariabelBerkas} — namaVariabelBerkas adalah Key dari field File Upload di form. Contoh body:
{
"nomor_aplikasi": "${nomorAplikasi}",
"dokumen_ktp": "${ktp}"
}Saat Service Task berjalan, platform mengganti ${ktp} di posisi yang sama dengan nilai berikut:
Sebelum 2026.9.4 — isi berkas base64:
{
"nomor_aplikasi": "APP-2026-0001",
"dokumen_ktp": "JVBERi0xLjQKJcfsj6IK..."
}Sesudah 2026.9.4 — URL unduh bertanda tangan:
{
"nomor_aplikasi": "APP-2026-0001",
"dokumen_ktp": "https://app.contoh.com/api/v1/probis/public/form-attachments/6f1c2a4e-8b7d-4c39-9a51-0e2d3f4a5b6c/download?token=eyJ...abc.def..."
}Format URL-nya:
GET /api/v1/probis/public/form-attachments/{attachment_id}/download?token=<token>Host pada URL mengikuti alamat publik gateway instance, sehingga bisa dijangkau dari luar jaringan aplikasi.
Aturan URL unduh
| Aturan | Keterangan |
|---|---|
| Sekali pakai | Token hanya berlaku untuk satu permintaan unduh. Permintaan kedua dengan URL yang sama ditolak 401. Tidak bisa di-retry dengan URL yang sama. |
| Masa berlaku 15 menit | Dihitung sejak URL diterbitkan, yaitu saat Service Task berjalan. Bisa diubah administrator lewat FORM_ATTACHMENT_URL_TTL_SECONDS (batas atas 1 jam). |
| Tanpa autentikasi lain | Tidak perlu header Authorization; token di query string adalah kredensialnya. Jangan menaruh header autentikasi platform pada permintaan ini. |
| Terikat ke satu berkas | Token yang diterbitkan untuk satu berkas tidak bisa membuka berkas lain. |
| Satu URL per kemunculan placeholder | Kalau ${ktp} muncul dua kali di body, penerima mendapat dua URL berbeda, masing-masing sekali pakai. |
Konsekuensi untuk penerima: unduh berkas segera saat pesan diterima, di dalam alur pemrosesan yang sama. URL tidak boleh disimpan untuk diunduh nanti (antrean, batch malam hari), dan tidak boleh diakses dua kali — termasuk oleh pemindai tautan atau health check yang ikut membuka URL.
Token dianggap terpakai begitu permintaan diterima dan divalidasi, sebelum isi berkas dikirim. Unduhan yang terputus di tengah jalan, atau kegagalan storage pada saat itu, tetap menghabiskan token. Penerima yang gagal mengunduh tidak bisa mencoba lagi dengan URL yang sama; pemicunya harus dijalankan ulang dari sisi AlurKerja supaya URL baru diterbitkan.
Response unduh yang berhasil adalah isi berkas dengan Content-Type sesuai mime_type berkas dan header Content-Disposition: attachment yang membawa nama file asli.
| Status | Arti |
|---|---|
200 | Berkas dikirim |
400 | attachment_id di path bukan UUID yang valid |
401 | Token tidak ada, salah tanda tangan, kedaluwarsa, sudah dipakai, atau bukan untuk berkas ini. Kelima kasus ini sengaja tidak dibedakan di response |
404 | Berkas tidak ditemukan, termasuk bila objeknya sudah hilang dari storage |
501 | Instance belum dikonfigurasi untuk menerbitkan URL unduh |
Membedakan URL dan base64
Berkas yang di-upload sebelum rilis 2026.9.4 tetap tersimpan sebagai berkas biner dan tetap dikirim sebagai base64. Berkas baru dikirim sebagai URL. Selama proses lama masih berjalan, field yang sama bisa berisi base64 atau URL, tergantung kapan berkasnya di-upload.
Base64 tidak pernah mengandung karakter :, sehingga awalan http:// atau https:// membedakannya dengan pasti:
import re
import base64
import requests
def ambil_berkas(nilai: str) -> bytes:
# URL bertanda tangan (sesudah 2026.9.4)
if re.match(r"^https?://", nilai):
resp = requests.get(nilai, timeout=30)
resp.raise_for_status()
return resp.content
# base64 (berkas lama)
return base64.b64decode(nilai)Alternatifnya, cek path /api/v1/probis/public/form-attachments/ pada nilai tersebut. Jangan mengandalkan panjang string atau awalan base64 tertentu.
Kalau penerima Anda menyimpan nilai field ini ke database sendiri lalu memprosesnya belakangan, ubah alurnya: unduh dulu saat pesan masuk, simpan berkasnya, bukan URL-nya.
Kalau URL gagal diterbitkan
Penerbitan URL adalah bagian dari Service Task. Kalau gagal — layanan lampiran tidak terjangkau, menolak permintaan, atau tenant/instance proses tidak bisa ditentukan — Service Task gagal dan membuat incident. Request ke sistem luar tidak pernah dikirim, jadi penerima tidak akan pernah menerima metadata JSON mentah sebagai pengganti berkas. Setelah penyebabnya dibereskan, jalankan ulang Service Task dari incident.
Saklar "alihkan kegagalan ke Error Boundary Event" pada Service Task hanya menerjemahkan penolakan dari integrasi (respons HTTP error, penolakan addon). Kegagalan menerbitkan URL berkas bukan penolakan dari integrasi, sehingga tetap berakhir sebagai incident.
Hanya berlaku di body
Penggantian placeholder berkas menjadi URL (atau base64) hanya dilakukan pada:
- body konfigurasi API Call dengan metode
POST,PUT, atauPATCH; dan - payload (
parameters) addon.
Placeholder berkas di URL, query parameter, atau header tidak diganti menjadi URL unduh — yang tergantikan di sana adalah nilai variabelnya apa adanya, yaitu string JSON metadata. Jangan menaruh ${namaVariabelBerkas} di tempat-tempat itu.
Objek variables yang ikut dikirim ke addon juga berisi string JSON metadata, bukan URL. Addon yang butuh berkasnya harus mengambilnya dari nilai di parameters.
Isi Variabel Proses: Metadata JSON
Sesudah 2026.9.4, variabel proses untuk field File Upload bertipe String dan berisi JSON berikut:
{
"attachment_id": "6f1c2a4e-8b7d-4c39-9a51-0e2d3f4a5b6c",
"file_name": "ktp-budi.pdf",
"mime_type": "application/pdf",
"size": 248310
}| Field | Keterangan |
|---|---|
attachment_id | UUID lampiran. Dipakai di path URL unduh dan endpoint lampiran form |
file_name | Nama file asli |
mime_type | Tipe isi hasil deteksi server |
size | Ukuran dalam byte |
Respons upload dan halaman embed juga membawa type ("file_attachment") dan uploaded_at; kedua field itu tidak dipakai untuk mengenali metadata.
Key id tidak seragam antar pengirim. Form yang dikirim dari aplikasi App (app-new-react) mengisi UUID lampiran pada key id, sedangkan jalur lain (embed start-process, respons upload) memakai attachment_id. Pembaca variabel secara langsung — misalnya lewat engine-rest — wajib menerima keduanya: ambil attachment_id, dan kalau tidak ada, ambil id. Platform sendiri melakukan hal ini; sebuah nilai dikenali sebagai metadata lampiran bila berupa objek JSON dengan file_name dan UUID yang valid pada salah satu key tersebut.
def id_lampiran(meta: dict) -> str:
return meta.get("attachment_id") or meta["id"]Berkas biner tidak lagi masuk ke database engine; hanya string metadata ini yang tersimpan di variabel.
API Lampiran Form
Lampiran form mengikuti daur draft → commit:
- Saat pengguna memilih berkas di form, berkas langsung di-upload dan tersimpan sebagai draft. Respons upload berisi metadata di atas.
- Saat form disubmit, proses berjalan dan variabel berisi metadata tersebut. Engine mengikat (commit) lampiran ke process instance dan task-nya secara otomatis begitu variabel tertulis. Sejak itu lampiran berstatus committed.
- Draft yang tidak pernah di-commit (mis. berkas diganti sebelum submit, atau proses gagal start) dibersihkan otomatis oleh server; batas usia draft bawaannya 24 jam.
Aplikasi resmi (App, Studio, embed) sudah menjalankan daur ini sendiri. Endpoint di bawah relevan bagi Anda kalau membangun klien sendiri.
Versi login (JWT)
Header: Authorization: Bearer <token> dan x-active-tenant: <slug-workspace> (slug, bukan id numerik).
| Endpoint | Fungsi |
|---|---|
POST /api/v1/probis/form-attachments/upload | Upload berkas sebagai draft. multipart/form-data: file, process_key, field_name (wajib); process_instance_id, task_id (opsional, kosong untuk form start). Respons 201 berisi metadata. Batas 20 permintaan per menit per pengguna |
POST /api/v1/probis/form-attachments/finalize | Meng-commit draft. Body JSON: attachment_ids (wajib), process_instance_id, task_id. 200 bila semua id ter-commit, 409 bila ada yang tidak ter-commit (id salah, tenant lain, atau sudah dibersihkan) |
GET /api/v1/probis/form-attachments/allowed-types | Daftar ekstensi yang diizinkan dan max_size_mb |
DELETE /api/v1/probis/form-attachments/{id} | Menghapus draft milik sendiri. 204; 404 bila bukan miliknya atau tidak ada; 409 bila sudah committed |
GET /api/v1/probis/form-attachments/{id}/download | Unduh dengan sesi login. Hanya pengunggah atau peserta diskusi process instance-nya; selain itu 404 |
Ekstensi yang diterima: jpg, jpeg, png, pdf, docx, xlsx (tipe isi diperiksa, bukan hanya ekstensi). Ukuran maksimum per berkas bawaan 10 MB, diatur administrator lewat UPLOAD_MAX_SIZE.
Versi public (embed start-process)
Untuk form start-process yang di-embed — pengunjung tanpa login. Identitas pengunjung adalah token sesi form pada header X-Probis-Form-Token yang dibawa halaman embed; tenant dan proses diambil dari token itu, bukan dari request.
| Endpoint | Fungsi |
|---|---|
POST /api/v1/probis/public/form-attachments/upload | Upload draft. multipart/form-data: file, field_name. Batas 30 permintaan per menit per IP; maksimum 10 berkas dan total ukuran dua kali batas per berkas per sesi form |
DELETE /api/v1/probis/public/form-attachments/{id} | Menghapus draft yang diunggah oleh sesi form yang sama |
GET /api/v1/probis/public/form-attachments/allowed-types | Daftar ekstensi yang diizinkan |
GET /api/v1/probis/public/form-attachments/{id}/download?token=… | Unduh dengan URL bertanda tangan (lihat bagian atas) |
Jalur public tidak punya endpoint finalize: pengikatan lampiran dilakukan engine sendiri setelah proses berhasil berjalan.
Nilai Variabel Berkas di Tasklist dan Report
Bentuk nilai (value) variabel berkas yang dibaca dari tasklist/report ikut berubah:
| Berkas lama (tipe File) | Berkas baru (metadata lampiran) | |
|---|---|---|
Bentuk value | Path relatif /{processKey}/download/{processInstanceId}/{namaVariabel} | Path absolut /api/v1/probis/form-attachments/{attachment_id}/download |
| Field tambahan | filename, size | filename, size, mime_type |
| Cara mengunduh | Relatif terhadap base tasklist (/api/v1/tasklist) | Dipakai apa adanya dari root gateway; butuh sesi login (JWT + x-active-tenant) |
Aturannya satu untuk semua konsumen: value yang diawali /api/v1/ adalah path absolut dari root gateway dan dipakai apa adanya; nilai lain relatif terhadap base tasklist. Untuk berkas lama, awalan /{processKey}/ pada laporan berisi process definition key.
Path pada tabel di atas adalah jalur dengan login, untuk pengguna aplikasi. Sistem luar yang tidak punya sesi login memakai URL bertanda tangan dari bagian Isi Placeholder.
Bukan Jalur Ini
Tidak semua "upload file" di AlurKerja memakai mekanisme di halaman ini. Kalau kebutuhan Anda salah satu di bawah, jalur yang berlaku berbeda:
| Kebutuhan | Jalur | Keterangan |
|---|---|---|
| Upload umum ke object storage (MinIO/S3) | POST /api/v1/integration/upload | Tanpa metadata dan tanpa daur draft → commit. Lihat API Upload File |
| Lampiran pesan diskusi | Endpoint diskusi (/api/v1/probis/discussions/…) | Lampiran diskusi punya id dan aturan akses sendiri, tidak lewat form-attachments |
| Kolom bertipe file pada record master data | Upload umum di atas; nilai record berupa path url | Bukan lampiran form. Lihat Master Data |
