Menu dokumentasi
Tarif
Cek ongkir yang bisa dipesan.
Cek tarif
https://api.ongkirhub.com/v1/rates Hitung ongkir semua layanan yang tersedia untuk paket ini, termurah dulu. Respons adalah penawaran yang bisa dipesan selama 30 menit. Untuk PICKUP, setiap layanan membawa pickupSlots.
Akses (scope): rates:read.
Butuh kunci API (bearerAuth)
Header
| Field | Keterangan |
|---|---|
Idempotency-Key string | Kunci unik dari sistem kamu (misalnya ID pesanan) agar permintaan yang diulang tidak diproses dua kali. Berlaku 24 jam. |
Body permintaan application/json
| Field | Keterangan |
|---|---|
sender Sender, wajib | - |
receiver Receiver, wajib | - |
items array<Item>, wajib | - min 1 item, maks 50 item |
pickupType string, wajib | PICKUP: kurir menjemput. DROP: kamu antar ke gerai kurir.
Nilai:
|
insured boolean | Tambahkan asuransi. Biaya asuransi per layanan ada di price.insurancePrice. bawaan false |
Contoh permintaan
curl -X POST "https://api.ongkirhub.com/v1/rates" \
-H "Authorization: Bearer ohk_test_xxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2a9e-4b7d-4c1e-9a52-3e8d0b7f1a24" \
-d '{
"sender": {
"name": "Toko Contoh Jaya",
"phone": "081200000001",
"email": "gudang@contoh.test",
"address": "Jl. Contoh Raya No. 1, RT 01/RW 02, Setiabudi",
"location": {
"province": "DKI Jakarta",
"city": "Jakarta Selatan",
"district": "Setia Budi",
"subdistrict": "Setiabudi",
"zipcode": "12910"
}
},
"receiver": {
"name": "Dimas Pratama",
"phone": "081300000102",
"address": "Jl. Penerima No. 2, dekat masjid, Lebak Gede",
"location": {
"province": "Jawa Barat",
"city": "Bandung",
"district": "Coblong",
"subdistrict": "Lebak Gede",
"zipcode": "40132"
}
},
"items": [
{
"name": "Kaos katun",
"sku": "KAOS-HITAM-L",
"qty": 2,
"weightKg": 0.5,
"value": 85000,
"dimensions": {
"lengthCm": 25,
"widthCm": 20,
"heightCm": 5
}
}
],
"pickupType": "DROP",
"insured": false
}' Respons
-
Penawaran.
-
X-Request-Id - ID permintaan untuk dukungan.
-
RateLimit-Limit - Batas permintaan per jendela waktu.
-
RateLimit-Remaining - Sisa permintaan di jendela waktu ini.
-
RateLimit-Reset - Detik sampai jendela waktu berikutnya.
-
Idempotent-Replayed - true jika respons ini adalah ulangan respons yang tersimpan untuk Idempotency-Key yang sama.
Field respons 200 Field Keterangan idstring, wajibID penawaran (quoteId). Berlaku 30 menit.
livemodeboolean, wajibFalse untuk kunci test.
pickupTypestring, wajib-
Nilai:
PICKUPDROPinsuredboolean, wajibPenawaran dengan asuransi.
expiresAtstring (date-time), wajibBatas penawaran bisa dipakai.
ratesarray<Rate>, wajibLayanan yang tersedia, termurah dulu.
{ "id": "6709f1c2a1b2c3d4e5f60718", "livemode": false, "pickupType": "DROP", "insured": false, "expiresAt": "2026-10-11T03:30:00.000Z", "rates": [ { "rateCode": "JAGOPACK", "courierCode": "lion", "courierName": "Lion Parcel", "serviceName": "JAGOPACK", "etd": { "min": 2, "max": 5, "unit": "DAY" }, "price": { "courierPrice": 9500, "insurancePrice": 0, "serviceFee": 0, "total": 9500 }, "chargeableWeightKg": 1, "pickupToday": false, "pickupSlots": null }, { "rateCode": "REG23", "courierCode": "jne", "courierName": "JNE", "serviceName": "Reguler", "etd": { "min": 1, "max": 2, "unit": "DAY" }, "price": { "courierPrice": 12000, "insurancePrice": 0, "serviceFee": 0, "total": 12000 }, "chargeableWeightKg": 1, "pickupToday": false, "pickupSlots": null }, { "rateCode": "EZ", "courierCode": "jnt", "courierName": "J&T Express", "serviceName": "Reguler", "etd": { "min": 2, "max": 3, "unit": "DAY" }, "price": { "courierPrice": 15000, "insurancePrice": 0, "serviceFee": 0, "total": 15000 }, "chargeableWeightKg": 1, "pickupToday": false, "pickupSlots": null } ] } -
-
Permintaan tidak bisa dibaca: JSON rusak, cursor atau Idempotency-Key tidak valid.
-
X-Request-Id - ID permintaan untuk dukungan.
-
RateLimit-Limit - Batas permintaan per jendela waktu.
-
RateLimit-Remaining - Sisa permintaan di jendela waktu ini.
-
RateLimit-Reset - Detik sampai jendela waktu berikutnya.
{ "error": { "code": "invalid_request", "message": "Body bukan JSON yang valid.", "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12" } } -
-
Kunci API tidak dikirim, tidak valid, atau sudah dicabut.
-
X-Request-Id - ID permintaan untuk dukungan.
{ "error": { "code": "unauthenticated", "message": "Kunci API tidak valid, sudah dicabut, atau tidak dikirim. Kirim header Authorization: Bearer <kunci API>.", "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12" } } -
-
Kunci API tidak punya akses (scope) untuk endpoint ini.
-
X-Request-Id - ID permintaan untuk dukungan.
-
RateLimit-Limit - Batas permintaan per jendela waktu.
-
RateLimit-Remaining - Sisa permintaan di jendela waktu ini.
-
RateLimit-Reset - Detik sampai jendela waktu berikutnya.
{ "error": { "code": "forbidden", "message": "Kunci API ini tidak punya akses ke endpoint ini. Tambahkan akses yang dibutuhkan di menu Developer.", "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12", "details": { "requiredScope": "shipments:write" } } } -
-
Permintaan dengan Idempotency-Key yang sama masih diproses.
-
X-Request-Id - ID permintaan untuk dukungan.
-
RateLimit-Limit - Batas permintaan per jendela waktu.
-
RateLimit-Remaining - Sisa permintaan di jendela waktu ini.
-
RateLimit-Reset - Detik sampai jendela waktu berikutnya.
{ "error": { "code": "idempotency_conflict", "message": "Permintaan dengan Idempotency-Key yang sama masih diproses. Tunggu sebentar, lalu kirim ulang.", "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12" } } -
-
Body lebih dari 64 KB.
-
X-Request-Id - ID permintaan untuk dukungan.
-
RateLimit-Limit - Batas permintaan per jendela waktu.
-
RateLimit-Remaining - Sisa permintaan di jendela waktu ini.
-
RateLimit-Reset - Detik sampai jendela waktu berikutnya.
{ "error": { "code": "payload_too_large", "message": "Body permintaan terlalu besar. Maksimal 64 KB.", "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12", "details": { "maxBytes": 65536 } } } -
-
Body bukan application/json.
-
X-Request-Id - ID permintaan untuk dukungan.
-
RateLimit-Limit - Batas permintaan per jendela waktu.
-
RateLimit-Remaining - Sisa permintaan di jendela waktu ini.
-
RateLimit-Reset - Detik sampai jendela waktu berikutnya.
{ "error": { "code": "unsupported_media_type", "message": "Kirim body sebagai JSON dengan header Content-Type: application/json.", "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12" } } -
-
Isi belum valid, tidak ada layanan untuk rute ini, atau Idempotency-Key dipakai untuk isi lain.
-
X-Request-Id - ID permintaan untuk dukungan.
-
RateLimit-Limit - Batas permintaan per jendela waktu.
-
RateLimit-Remaining - Sisa permintaan di jendela waktu ini.
-
RateLimit-Reset - Detik sampai jendela waktu berikutnya.
Isian belum valid
{ "error": { "code": "validation_error", "message": "Ada data yang belum lengkap atau belum sesuai. Periksa lagi isianmu.", "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12", "details": { "fields": [ { "path": "items.0.weightKg", "message": "Berat harus lebih dari 0 kg" } ] } } }Tidak ada layanan
{ "error": { "code": "no_rates_available", "message": "Belum ada layanan kurir untuk rute dan paket ini. Coba ubah alamat atau berat paket.", "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12" } }Idempotency-Key untuk isi lain
{ "error": { "code": "idempotency_key_reused", "message": "Idempotency-Key ini sudah dipakai untuk permintaan lain. Pakai kunci baru untuk permintaan yang berbeda.", "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12" } } -
-
Batas permintaan terlampaui.
-
X-Request-Id - ID permintaan untuk dukungan.
-
RateLimit-Limit - Batas permintaan per jendela waktu.
-
RateLimit-Remaining - Sisa permintaan di jendela waktu ini.
-
RateLimit-Reset - Detik sampai jendela waktu berikutnya.
-
Retry-After - Detik sampai boleh mencoba lagi.
{ "error": { "code": "rate_limited", "message": "Terlalu banyak permintaan. Tunggu sebentar, lalu coba lagi.", "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12", "details": { "retryAfterSec": 21 } } } -
-
Kesalahan di sistem OngkirHub. Aman dicoba ulang dengan Idempotency-Key yang sama.
-
X-Request-Id - ID permintaan untuk dukungan.
-
RateLimit-Limit - Batas permintaan per jendela waktu.
-
RateLimit-Remaining - Sisa permintaan di jendela waktu ini.
-
RateLimit-Reset - Detik sampai jendela waktu berikutnya.
{ "error": { "code": "internal_error", "message": "Terjadi kesalahan di sistem kami. Coba lagi sebentar lagi.", "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12" } } -
-
Layanan pengiriman sedang gangguan atau pembuatan resi sedang dijeda. Coba lagi nanti.
-
X-Request-Id - ID permintaan untuk dukungan.
-
RateLimit-Limit - Batas permintaan per jendela waktu.
-
RateLimit-Remaining - Sisa permintaan di jendela waktu ini.
-
RateLimit-Reset - Detik sampai jendela waktu berikutnya.
Layanan pengiriman gangguan
{ "error": { "code": "service_unavailable", "message": "Layanan pengiriman sedang gangguan. Coba lagi beberapa saat lagi.", "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12" } }Pembuatan resi dijeda
{ "error": { "code": "booking_disabled", "message": "Pembuatan resi sedang dijeda sementara. Cek ongkir dan cek resi tetap bisa dipakai.", "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12" } } -
-
Layanan pengiriman lambat merespons. Coba lagi.
-
X-Request-Id - ID permintaan untuk dukungan.
-
RateLimit-Limit - Batas permintaan per jendela waktu.
-
RateLimit-Remaining - Sisa permintaan di jendela waktu ini.
-
RateLimit-Reset - Detik sampai jendela waktu berikutnya.
{ "error": { "code": "service_timeout", "message": "Layanan pengiriman sedang lambat. Coba lagi sebentar lagi.", "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12" } } -
Skema objek
Objek yang dipakai di halaman ini, dijelaskan sekali di sini.
Sender
| Field | Keterangan |
|---|---|
name string, wajib | Nama pengirim. min 2 karakter, maks 100 karakter |
phone string, wajib | Nomor HP Indonesia. Diterima 08…, +62… atau 62…; disimpan sebagai 62 diikuti angka. |
email string (email), wajib | Email pengirim, wajib untuk pembuatan resi. maks 254 karakter |
address string, wajib | Alamat lengkap: jalan, nomor, RT/RW, patokan. min 10 karakter, maks 500 karakter |
location Location, wajib | Wilayah tujuan atau asal. Ambil dari GET /v1/locations agar cocok dengan data kurir. |
latlng LatLng | Titik lokasi. Hanya wajib untuk layanan dengan requiresCoordinates. |
Location
Wilayah tujuan atau asal. Ambil dari GET /v1/locations agar cocok dengan data kurir.
| Field | Keterangan |
|---|---|
province string, wajib | Provinsi, ditulis persis seperti hasil GET /v1/locations. |
city string, wajib | Kota atau kabupaten. |
district string, wajib | Kecamatan. |
subdistrict string, wajib | Kelurahan atau desa. |
zipcode string, wajib | Kode pos 5 digit. pola ^\d{5}$ |
LatLng
Titik lokasi. Hanya wajib untuk layanan dengan requiresCoordinates.
| Field | Keterangan |
|---|---|
lat number, wajib | Latitude, di dalam wilayah Indonesia. min -11.5, maks 6.5 |
lng number, wajib | Longitude, di dalam wilayah Indonesia. min 94, maks 141.5 |
Receiver
| Field | Keterangan |
|---|---|
name string, wajib | Nama penerima. min 2 karakter, maks 100 karakter |
phone string, wajib | Nomor HP Indonesia. Diterima 08…, +62… atau 62…; disimpan sebagai 62 diikuti angka. |
email string (email) | Email penerima (opsional). maks 254 karakter |
address string, wajib | Alamat lengkap: jalan, nomor, RT/RW, patokan. min 10 karakter, maks 500 karakter |
location Location, wajib | Wilayah tujuan atau asal. Ambil dari GET /v1/locations agar cocok dengan data kurir. |
latlng LatLng | Titik lokasi. Hanya wajib untuk layanan dengan requiresCoordinates. |
Item
| Field | Keterangan |
|---|---|
name string, wajib | Nama barang. min 1 karakter, maks 200 karakter |
sku string | SKU (opsional). maks 64 karakter |
qty integer, wajib | Jumlah. min 1, maks 1000 |
weightKg number, wajib | Berat satu unit dalam kg. maks 1000 |
dimensions Dimensions | - |
value integer, wajib | Nilai satu unit dalam rupiah, dipakai untuk asuransi. min 0, maks 1000000000 |
itemType string | Jenis barang.
Nilai:
bawaan "REGULAR" |
Dimensions
| Field | Keterangan |
|---|---|
lengthCm number, wajib | Panjang dalam cm. maks 1000 |
widthCm number, wajib | Lebar dalam cm. maks 1000 |
heightCm number, wajib | Tinggi dalam cm. maks 1000 |
Rate
| Field | Keterangan |
|---|---|
rateCode string, wajib | Kode layanan, dipakai saat membuat pengiriman. |
courierCode string | null, wajib | Kode kurir.
Nilai:
|
courierName string, wajib | Nama kurir. |
serviceName string, wajib | Nama layanan. |
etd Etd | null, wajib | Estimasi waktu sampai dari kurir. |
price PriceBreakdown, wajib | - |
chargeableWeightKg number | null, wajib | Berat yang ditagihkan kurir (berat asli atau volumetrik). |
pickupToday boolean, wajib | Kurir masih bisa menjemput hari ini. |
pickupSlots array<PickupSlot> | null, wajib | Untuk penawaran PICKUP: jadwal jemput dua hari ke depan. Null untuk DROP atau jika jadwal sedang tidak tersedia. |
Etd
Estimasi waktu sampai dari kurir.
| Field | Keterangan |
|---|---|
min integer, wajib | Estimasi tercepat. |
max integer, wajib | Estimasi terlama. |
unit string, wajib | -
Nilai:
|
PriceBreakdown
| Field | Keterangan |
|---|---|
courierPrice integer, wajib | Ongkir dari kurir. Rupiah, bilangan bulat. |
insurancePrice integer, wajib | Biaya asuransi (0 jika tidak diasuransikan). Rupiah, bilangan bulat. |
serviceFee integer, wajib | Biaya layanan OngkirHub (saat ini Rp0). Rupiah, bilangan bulat. |
total integer, wajib | Total yang dipotong dari saldo. Rupiah, bilangan bulat. |
PickupSlot
| Field | Keterangan |
|---|---|
startAt string (date-time), wajib | Awal jadwal jemput (WIB, +07:00). Kirim sebagai pickupTime. |
endAt string (date-time), wajib | Akhir jadwal jemput. |
label string, wajib | Label jadwal, contoh 08.00 - 22.00. |