API Upload File
Mengunggah file ke object storage (MinIO/S3) lewat endpoint upload umum, dan mengambilnya kembali lewat URL publik.
Gambaran Umum
AlurKerja menyediakan satu endpoint upload umum yang menyimpan file ke object storage instance (MinIO, atau S3/COS pada instalasi cloud) dan mengembalikan path objek yang bisa disimpan sendiri oleh pemanggil — misalnya ke kolom master data, ke field custom, atau ke sistem luar.
Endpointnya sepasang:
| Kegunaan | Endpoint | Autentikasi |
|---|---|---|
| Mengunggah file | POST /api/v1/integration/upload | Bearer token + role Admin SOP atau Owner |
| Mengambil file kembali | GET /api/v1/integration/public/{path} | Tidak ada — publik |
Seluruh file masuk ke satu bucket yang dikonfigurasi di server (MINIO_BUCKET_NAME). Pemanggil tidak bisa memilih bucket; yang bisa diatur hanya folder di dalam bucket tersebut.
Kapan Memakai Endpoint Ini
Endpoint ini adalah jalur upload umum. Untuk tiga kebutuhan berikut sudah ada endpoint khusus yang menyimpan metadata, memvalidasi tipe file, dan mengikat file ke objek bisnisnya — jangan memakai endpoint umum untuk ketiganya:
| Kebutuhan | Pakai | Alasan |
|---|---|---|
| Lampiran pada field File Upload di form BPMN | POST /api/v1/probis/form-attachments/upload | Memvalidasi ekstensi (jpg, jpeg, png, pdf, docx, xlsx) dan sniffing MIME, menyimpan baris metadata, serta mengikat lampiran ke process instance lewat mekanisme draft → commit. Lihat File Upload dan Berkas Form BPMN untuk Integrasi Pihak Ketiga. |
| Media Company Profile / Microsite | POST /api/v1/compro/media/upload | File tercatat sebagai media dan terikat ke entitasnya, sehingga bisa dikelola ulang dari Studio. |
Paket addon (.zip) | POST /api/v1/integration/addons/upload | Ada proses ekstraksi dan registrasi addon setelah upload. |
Endpoint umum ini tidak memvalidasi ekstensi maupun tipe isi file, dan tidak menyimpan baris metadata apa pun. Yang tersimpan hanyalah objeknya di bucket; hubungan file dengan data bisnis sepenuhnya menjadi tanggung jawab pemanggil.
Di dalam produk, endpoint ini dipakai oleh kolom bertipe file pada Master Data: nilai yang disimpan ke record adalah string url hasil upload.
Mengunggah File
POST /api/v1/integration/upload
Content-Type: multipart/form-data
Authorization: Bearer <token>
x-active-tenant: <slug-workspace>| Header | Wajib | Keterangan |
|---|---|---|
Authorization | Ya | Bearer <token> milik pengguna ber-role Admin SOP atau Owner di workspace tersebut |
x-active-tenant | Ya | Slug workspace, bukan id numerik. Mengisi angka akan ditolak sebagai bukan anggota workspace |
| Field form-data | Wajib | Keterangan |
|---|---|---|
file | Ya | Berkas yang diunggah. Namanya harus persis file |
folder | Tidak | Prefix folder di dalam bucket, mis. master-data/pelanggan. Boleh bertingkat. Kalau kosong, objek ditaruh di root bucket |
Contoh:
curl -X POST "https://app.contoh.com/api/v1/integration/upload" \
-H "Authorization: Bearer $TOKEN" \
-H "x-active-tenant: workspace-saya" \
-F "file=@ktp-budi.pdf" \
-F "folder=master-data/pelanggan"Response 200 OK:
{
"status": "success",
"message": "File uploaded successfully",
"data": {
"file_name": "ktp-budi.pdf",
"object_name": "master-data/pelanggan/ktp-budi_1758790000.pdf",
"url": "/tenant-uploads/master-data/pelanggan/ktp-budi_1758790000.pdf",
"size": 248310
}
}| Field response | Keterangan |
|---|---|
file_name | Nama file asli seperti yang dikirim pemanggil |
object_name | Key objek di dalam bucket, sudah termasuk folder |
url | /<nama-bucket>/<object_name> — path relatif, bukan URL lengkap. Ini nilai yang biasanya disimpan ke database pemanggil |
size | Ukuran objek dalam byte, dibaca dari hasil tulis ke storage |
Aturan penamaan objek
Nama objek dibentuk dari nama file asli dengan sisipan unix timestamp (detik) sebelum ekstensi:
laporan-q3.xlsx → laporan-q3_1758790000.xlsxBeberapa konsekuensi yang perlu diketahui:
- Nama file asli dipertahankan apa adanya. Spasi, tanda kurung, dan karakter non-ASCII ikut masuk ke key objek — URL unduhannya wajib di-URL-encode saat dipakai di
hrefatau di pemanggil lain. - Komponen direktori pada nama file dibuang. File bernama
../../etc/ktp.pdftersimpan sebagaiktp.pdf; nama file tidak bisa dipakai untuk keluar dari folder. - Resolusinya per detik, bukan per milidetik. Dua upload dengan nama file yang sama, ke folder yang sama, pada detik yang sama akan menghasilkan key yang sama — yang kedua menimpa yang pertama tanpa pesan error apa pun.
Object key tidak mengandung identitas workspace. Kalau dua workspace pada satu instance memakai nilai folder yang sama, keduanya menulis ke ruang nama yang sama di bucket yang sama. Sertakan pembeda di folder (mis. master-data/<slug-workspace>/pelanggan) kalau instance dipakai lebih dari satu workspace.
Mengambil File Kembali
GET /api/v1/integration/public/{path}Nilai url dari response upload bisa langsung ditempel di belakang /api/v1/integration/public:
https://app.contoh.com/api/v1/integration/public/tenant-uploads/master-data/pelanggan/ktp-budi_1758790000.pdfDua bentuk path diterima dan menunjuk objek yang sama:
| Bentuk | Contoh | Perlakuan |
|---|---|---|
| Diawali nama bucket yang dikonfigurasi | /public/tenant-uploads/master-data/ktp_175....pdf | Segmen pertama dianggap nama bucket dan dibuang dari key |
| Tanpa nama bucket | /public/master-data/ktp_175....pdf | Seluruh path dianggap key objek |
Artinya endpoint ini selalu membaca dari bucket yang dikonfigurasi di server; tidak ada cara meminta objek dari bucket lain lewat URL.
Response-nya adalah isi file dengan Content-Type sesuai yang tersimpan saat upload, dan header Content-Disposition: attachment — browser akan mengunduh, bukan menampilkan inline.
Endpoint unduh ini publik dan tanpa autentikasi, sementara nama objek dibentuk dari nama file asli ditambah timestamp detik. Siapa pun yang tahu (atau menebak) path objeknya bisa mengunduh isinya, termasuk dari luar workspace. Jangan memakai endpoint upload umum ini untuk dokumen yang bersifat rahasia — untuk lampiran yang perlu terkendali, pakai lampiran form BPMN yang aksesnya melewati pemeriksaan hak di sisi server.
Kode Status
| Status | Kapan muncul | Body |
|---|---|---|
200 | Upload berhasil | {"status":"success","message":"File uploaded successfully","data":{…}} |
401 | Token tidak ada atau tidak valid | {"error":"…"} |
403 | Token valid tapi role di workspace bukan Admin SOP/Owner, atau x-active-tenant menunjuk workspace yang bukan miliknya | {"error":"…"} |
413 | Body melebihi batas ukuran (lihat bagian berikut) | ditentukan oleh proxy/gateway |
500 | Gagal menulis ke object storage | {"status":"error","message":"Failed to upload file"} |
Permintaan tanpa field file juga dijawab 500 Failed to upload file, bukan 400. Jadi status 500 pada endpoint ini tidak selalu berarti object storage bermasalah — periksa dulu nama field pada form-data-nya (harus persis file). Perilaku ini berlaku pada versi saat ini.
Untuk endpoint unduh:
| Status | Kapan muncul |
|---|---|
200 | Objek ditemukan dan dikirim |
400 | Path objek kosong, atau bucket belum dikonfigurasi di server |
404 | Objek tidak ada di bucket |
Batas Ukuran File
Tidak ada satu angka tunggal — yang berlaku adalah batas terkecil di sepanjang jalur permintaan:
| Lapisan | Batas | Pengaturan |
|---|---|---|
| Integration Service | 100 MB | Tetap, tidak lewat env |
| Proxy / gateway AlurKerja | 80 MB (bawaan) | MAX_REQUEST_BODY_SIZE, wajib memakai satuan eksplisit seperti 80MB atau 100MiB — angka telanjang ditolak saat start |
| Reverse proxy di depannya (mis. nginx) | tergantung instalasi | client_max_body_size |
Jadi pada instalasi standar, batas efektifnya 80 MB.
Pada instalasi yang masih memakai image proxy-service lama (sebelum perbaikan 30 Agustus 2026), batas body terkunci di 4 MiB bawaan framework dan tidak bisa dinaikkan lewat environment variable. Gejalanya: upload file beberapa MB gagal dengan 413 padahal MAX_REQUEST_BODY_SIZE sudah diisi besar. Solusinya memperbarui image proxy, bukan mengubah konfigurasi.
Konfigurasi Server
Endpoint ini membaca konfigurasi object storage dari environment variable berikut pada Integration Service:
| Variable | Bawaan | Keterangan |
|---|---|---|
MINIO_ENDPOINT | — | Host object storage, mis. minio:9000 (tanpa skema) |
MINIO_ACCESS_KEY | — | Access key. Tidak perlu diisi kalau memakai IAM role |
MINIO_SECRET_KEY | — | Secret key. Tidak perlu diisi kalau memakai IAM role |
MINIO_BUCKET_NAME | tenant-uploads | Bucket tujuan upload sekaligus satu-satunya bucket yang bisa dibaca endpoint unduh |
MINIO_USE_SSL | false | Isi true kalau endpoint diakses lewat HTTPS |
MINIO_BUCKET_LOOKUP | kosong (auto) | Isi dns untuk Tencent COS; biarkan kosong untuk MinIO |
AWS_IRSA_ENABLED | false | Isi true untuk memakai IAM role (AWS IRSA) alih-alih access key statis |
AWS_REGION | ap-southeast-1 | Hanya dipakai saat AWS_IRSA_ENABLED=true |
Kalau bucket belum ada, service akan mencoba membuatnya pada upload pertama. Kredensial yang dipakai karena itu perlu izin membuat bucket, atau bucket-nya disiapkan lebih dulu oleh administrator.
Pola Pemakaian yang Umum
- Kirim file ke
POST /api/v1/integration/uploadbersamafolderyang menjelaskan asal datanya. - Simpan nilai
urldari response ke record milik Anda (kolom master data, variable proses, atau sistem luar) — bukanobject_name, supaya prefix bucket ikut tersimpan. - Saat perlu menampilkan, rangkai tautan
"<base-url>/api/v1/integration/public" + url, dan lakukan URL-encode bila nama file mengandung spasi atau karakter khusus.
Kalau file yang diunggah harus mengikuti daur hidup proses (ikut terhapus saat draft dibatalkan, ikut tercatat di histori task), gunakan lampiran form BPMN, bukan pola di atas.
Schema Builder API
API dan menu Database Tables di Studio untuk membuat dan mengelola tabel transaksi milik tenant sendiri (DDL/DML) tanpa menulis SQL mentah.
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.
