Format error Developer API OngkirHub, arti setiap kode error beserta status HTTP-nya, isi details, dan cara menanganinya di integrasimu.
Semua error memakai format yang sama. Pakai code untuk logika integrasimu, dan tampilkan message ke pengguna bila perlu.
{
"error": {
"code": "validation_error",
"message": "Ada data yang belum lengkap atau belum sesuai. Periksa lagi isianmu.",
"request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12",
"details": {
"fields": [{ "path": "receiver.location.zipcode", "message": "Kode pos harus 5 digit" }]
}
}
}
| Field |
Keterangan |
code |
Kode yang stabil. Aman dipakai di logika integrasi. |
message |
Penjelasan dalam Bahasa Indonesia, aman ditampilkan ke pengguna. Teksnya bisa berubah, jadi jangan dipakai di logika. |
request_id |
ID permintaan, sama dengan header X-Request-Id. Sertakan saat menghubungi tim OngkirHub. |
details |
Opsional. Detail tambahan sesuai jenis error, lihat tabel di bawah. |
Setiap respons, sukses maupun error, membawa header X-Request-Id. Simpan nilainya di log servermu, karena hanya log milikmu yang pasti memuat setiap permintaan.
Tab Log API di menu Developer menyimpan permintaan selama 30 hari, tetapi paling banyak 60 permintaan per kunci per 60 detik, ditambah penolakan 429 pertama di jendela itu. Permintaan lain tetap diproses seperti biasa, hanya tidak muncul di Log API. Jadi request_id sebuah permintaan bisa saja tidak ada di sana. Untuk error 5xx, request_id tetap tercatat di log sistem kami meskipun tidak muncul di Log API. Untuk respons lain di luar batas log, simpan X-Request-Id di log server kamu.
Isi details
| Field |
Muncul pada |
Isi |
fields |
validation_error |
Daftar field yang perlu diperbaiki, masing-masing dengan path (contoh receiver.phone) dan message. |
requiredScope |
forbidden |
Akses yang dibutuhkan endpoint ini. |
retryAfterSec |
rate_limited |
Detik sampai boleh mencoba lagi. |
quoteId |
quote_expired |
Penawaran baru dengan harga terbaru, bila harga berubah saat dicek ulang. |
shipmentId |
idempotency_conflict |
Pengiriman yang sudah memakai penawaran ini. |
available, required |
wallet_insufficient_funds |
Saldo tersedia dan saldo yang dibutuhkan, dalam rupiah. |
maxBytes |
payload_too_large |
Ukuran body maksimal dalam byte. |
Kode yang dikirim sebagai respons
Permintaan dan autentikasi
| Status |
code |
Artinya |
Yang perlu dilakukan |
| 400 |
invalid_request |
Body bukan JSON yang valid atau bukan objek, parameter cursor tidak valid, atau Idempotency-Key tidak sesuai format. |
Perbaiki permintaan. Mengulang tanpa perubahan memberi hasil yang sama. |
| 401 |
unauthenticated |
Kunci API tidak dikirim, salah, atau sudah dicabut. |
Periksa header Authorization: Bearer <kunci>. Lihat Autentikasi. |
| 403 |
forbidden |
Kunci tidak punya akses untuk endpoint ini. |
Buat kunci dengan akses di details.requiredScope. |
| 404 |
not_found |
Pengiriman tidak ditemukan untuk kunci ini, atau path endpoint tidak dikenal. |
Pastikan ID benar dan kunci memakai mode yang sama dengan pengirimannya. |
| 405 |
method_not_allowed |
Metode HTTP tidak didukung endpoint ini. |
Cek metode di referensi API. |
| 413 |
payload_too_large |
Body lebih dari 64 KB. |
Kurangi isi body. |
| 415 |
unsupported_media_type |
Body dikirim tanpa Content-Type: application/json. |
Tambahkan header itu. |
| 422 |
validation_error |
Ada field yang kosong, salah format, atau di luar batas. |
Perbaiki field di details.fields. |
| 429 |
rate_limited |
Batas permintaan terlampaui. |
Tunggu sesuai Retry-After. Lihat Rate limit. |
Idempotency
| Status |
code |
Artinya |
Yang perlu dilakukan |
| 409 |
idempotency_conflict |
Permintaan dengan Idempotency-Key yang sama masih diproses, kunci sudah terikat ke pengiriman lain (mode lain, atau isi berbeda setelah 24 jam), atau penawaran sudah dipakai pengiriman lain (details.shipmentId). message menjelaskan penyebabnya. |
Masih diproses: tunggu lalu ulangi. Kunci terikat: jangan diulang, pakai kunci baru hanya untuk pengiriman yang berbeda. Penawaran terpakai: ambil pengiriman di details.shipmentId. Rinciannya di Idempotency. |
| 422 |
idempotency_key_reused |
Idempotency-Key sudah dipakai untuk isi permintaan yang berbeda. |
Pakai kunci baru untuk permintaan yang berbeda. Lihat Idempotency. |
Tarif dan pembuatan pengiriman
| Status |
code |
Artinya |
Yang perlu dilakukan |
| 402 |
wallet_insufficient_funds |
Saldo tersedia kurang dari total harga. Di mode test, saldo uji yang kurang. |
Isi saldo, lalu buat pengiriman lagi dengan Idempotency-Key baru. |
| 409 |
quote_expired |
Penawaran tidak ditemukan, sudah lewat 30 menit, rateCode tidak ada di penawaran, atau harga berubah saat dicek ulang. |
Cek tarif lagi. Bila ada details.quoteId, tampilkan harga barunya ke pengguna sebelum memesan. |
| 422 |
no_rates_available |
Belum ada layanan untuk rute dan paket ini. |
Periksa lokasi asal dan tujuan, berat, atau pilihan pickupType. |
| 422 |
courier_service_unavailable |
Layanan yang dipilih sedang tidak tersedia. |
Pilih layanan lain dari hasil cek tarif. |
| 422 |
amount_limit_exceeded |
Total biaya melebihi batas per pengiriman untuk akunmu (mode live). |
Hubungi tim OngkirHub bila batasnya perlu dinaikkan. |
| 429 |
daily_limit_reached |
Batas pengiriman harian akunmu sudah tercapai (mode live). |
Coba lagi besok atau hubungi tim OngkirHub. |
| 503 |
booking_disabled |
Pembuatan resi sedang dijeda sementara. Cek tarif dan pelacakan tetap bisa dipakai. |
Coba lagi nanti. |
Pembatalan
| Status |
code |
Artinya |
Yang perlu dilakukan |
| 409 |
cancellation_not_allowed |
Pengiriman tidak berstatus booked, awb_ready, atau problem, atau pembatalannya sudah diajukan. |
Cek status pengiriman. Pembatalan hanya bisa diajukan dari tiga status itu. |
Pelacakan
| Status |
code |
Artinya |
Yang perlu dilakukan |
| 404 |
tracking_not_found |
Resi tidak ditemukan. Untuk resi dari luar OngkirHub, parameter courier belum dikirim atau kurir belum punya data resi itu. |
Periksa nomor resi dan kode kurir. Resi baru bisa butuh beberapa jam sampai dipindai kurir. |
| 422 |
tracking_verification_required |
Resi JNE dari luar OngkirHub butuh 5 digit terakhir nomor HP penerima. |
Kirim parameter verification. |
| 422 |
tracking_unsupported_courier |
Resi kurir ini dari luar OngkirHub belum bisa dilacak. |
Resi dari luar OngkirHub hanya didukung untuk JNE, J&T Express, dan AnterAja. |
Gangguan layanan
| Status |
code |
Artinya |
Yang perlu dilakukan |
| 500 |
internal_error |
Kesalahan di sistem OngkirHub. |
Ulangi dengan Idempotency-Key yang sama. Bila berulang, hubungi tim OngkirHub dengan request_id. |
| 503 |
service_unavailable |
Layanan pengiriman sedang gangguan. |
Ulangi beberapa saat lagi dengan jeda yang makin panjang. |
| 504 |
service_timeout |
Layanan pengiriman lambat merespons. |
Ulangi dengan Idempotency-Key yang sama. |
Respons 5xx dan 429 tidak disimpan oleh Idempotency-Key, jadi aman diulang dengan kunci yang sama.
Kode di field error pengiriman
POST /v1/shipments menjawab 201 sebelum pesanan sampai ke kurir. Kalau pesanan kemudian gagal atau perlu dicek ulang, alasannya tercatat di field error objek pengiriman (code dan message), dan kamu menerimanya lewat GET /v1/shipments/{id} atau event webhook. Kode yang paling sering muncul di sini:
code |
Status pengiriman |
Artinya |
courier_rejected |
failed |
Kurir menolak pesanan. Saldo yang ditahan sudah dikembalikan. Coba layanan lain. |
order_reconciling |
unknown |
Jawaban kurir belum diterima. OngkirHub mengecek ulang otomatis, statusnya berubah dalam beberapa menit. |
booking_disabled, service_unavailable, quote_expired |
failed |
Pesanan tidak bisa diteruskan karena pembuatan resi dijeda, layanan gangguan, atau penawaran tidak berlaku lagi saat pesanan diteruskan. Saldo yang ditahan dikembalikan. |
shipment_payment_expired |
expired |
Hanya untuk bayar langsung dari aplikasi, yang sedang tidak tersedia: waktu pembayaran habis. |
shipment_needs_rebooking |
expired |
Hanya untuk bayar langsung dari aplikasi, yang sedang tidak tersedia: pembayaran sudah masuk ke saldo, tetapi harga atau jadwal berubah sehingga resi perlu dibuat ulang. |
Kode lain dari daftar di halaman ini juga bisa muncul di field error. Selama status bukan failed atau expired, field ini hanya informasi dan pengiriman masih diproses.
Kode yang dipakai aplikasi
Kode berikut ada di daftar kode error OpenAPI karena dipakai bersama OngkirHub App. Endpoint v1 saat ini tidak mengirimnya sebagai respons, tetapi integrasimu sebaiknya tetap menangani kode yang tidak dikenal dengan aman.
code |
Dipakai untuk |
pickup_time_required |
Jadwal jemput belum dipilih. Di API, kondisi ini dilaporkan sebagai validation_error pada field pickupTime. |
coordinates_required |
Layanan yang butuh titik lokasi pengirim dan penerima. Di API, kondisi ini dilaporkan sebagai validation_error. |
tracking_courier_required |
Kurir untuk nomor resi perlu dipilih di cek resi. Di API, resi dari luar OngkirHub tanpa parameter courier dijawab 404 tracking_not_found. |
topup_below_minimum, topup_above_limit |
Nominal isi saldo di bawah minimum Rp10.000 atau di atas batas akun. |
payment_method_unavailable, payment_expired |
Metode pembayaran isi saldo sedang tidak tersedia, atau waktu pembayaran habis. |
claim_not_allowed, claim_already_open, upload_invalid |
Pengajuan klaim dan unggahan bukti di aplikasi. |
network_error |
Koneksi perangkat pengguna terputus saat memakai aplikasi. |
mail_unavailable |
Pengiriman email OngkirHub, misalnya kode verifikasi atau undangan tim, sedang dalam pemeliharaan. |
Menangani error dengan baik
- Tentukan tindakan dari status HTTP dan
code, bukan dari message.
- Anggap kode yang belum kamu kenal sebagai error umum: tampilkan
message, catat request_id, dan jangan mengulang otomatis kecuali statusnya 5xx atau 429.
- Ulangi hanya untuk 5xx,
429, timeout, dan 409 idempotency_conflict tanpa details.shipmentId, selalu dengan Idempotency-Key yang sama dan jeda yang makin panjang. Berhenti setelah beberapa kali bila error tetap sama.
- Simpan
request_id di log servermu dan sertakan saat menghubungi tim OngkirHub. Permintaan yang tidak tampil di Log API hanya bisa ditelusuri tim OngkirHub bila responsnya error 5xx.