Cara Cek Ongkir Multi-Kurir lewat API

Ditulis oleh Rifaldy Elninoru·Ditinjau oleh ·11 Oktober 2026·Diperbarui 9 Oktober 2026·Panduan Produk Api.co.id
Bagikan:

Cek ongkir multi-kurir lewat API dalam dua langkah

Di toko online, pembeli mau melihat pilihan ongkir dari beberapa kurir sekaligus sebelum menekan bayar di halaman checkout. Untuk menampilkan cek ongkir multi-kurir lewat API cek ongkir api.co.id, kamu memanggil GET /expedition/shipping-cost dengan tiga parameter: origin_village_code, destination_village_code, dan weight dalam kilogram. Satu api call mengembalikan tarif semua kurir yang melayani rute itu, dari JNE sampai Ninja. Satu hal yang perlu kamu tahu lebih dulu: alamat di sini dikunci lewat kode kelurahan 10 digit. Kamu tidak memakai ID kota, jadi langkah pertama adalah mengubah alamat pembeli jadi kode kelurahan.

Jadi ada dua produk yang kamu rangkai dalam alur ini. Pertama API Wilayah untuk mengubah alamat jadi kode kelurahan, lalu API Cek Ongkos Kirim untuk mengambil tarifnya. Keduanya jalan di host https://use.api.co.id dengan header x-api-co-id, jadi satu API key sudah cukup untuk keduanya.

Yang perlu disiapkan

Sebelum panggilan pertamamu jalan, ada beberapa hal yang kamu urus di dashboard api.co.id, yaitu:

  • Membuat akun di api.co.id
  • Mengambil API key di dashboard
  • Berlangganan Expedition (API Cek Ongkos Kirim)
  • Berlangganan API Wilayah

Kamu bisa daftar atau masuk di dashboard.api.co.id, lalu membuat API key di halaman kredensial. Kamu pasang API key itu di header x-api-co-id pada setiap panggilan, jadi simpan nilainya di tempat yang aman. Expedition memberi 50 hit gratis untuk kamu coba, sementara API Wilayah tidak punya kuota gratis, jadi langganannya kamu aktifkan dari awal. Rincian harganya ada di bagian harga di bawah.

Mengubah alamat jadi kode kelurahan lewat API Wilayah

Kenapa cek ongkir minta kode kelurahan 10 digit? Karena tarif dihitung sampai level kelurahan, dan tiap kelurahan punya kode unik. Satu nama kota saja terlalu kasar untuk perhitungan ini: di dalamnya ada ratusan kelurahan dengan tarif yang bisa berbeda. Kode itu bertingkat: provinsi 2 digit, kabupaten atau kota 4 digit, kecamatan 6 digit, dan kelurahan 10 digit. Jadi 31 (DKI Jakarta) melebar ke 3174 (Kota Jakarta Selatan), lalu 317405 (Kebayoran Lama), sampai 3174050001 (satu kelurahan). Kode 10 digit itu kamu ambil dari API Wilayah Indonesia.

Cara paling langsung adalah mencari kelurahan lewat nama. Untuk dropdown alamat kamu juga bisa pakai /autocomplete?query=&type=village, atau menelusuri hierarki /provinces ke /regencies ke /districts/{code}/villages. Contoh di bawah mencari lewat nama:

GET https://use.api.co.id/regional/indonesia/villages?name=grogol%20utara
x-api-co-id: YOUR_API_KEY

Tiap desa di hasil berbentuk seperti ini:

{
  "code": "3174050001",
  "name": "GROGOL UTARA",
  "district_code": "317405",
  "district": "KEBAYORAN LAMA",
  "regency_code": "3174",
  "regency": "KOTA JAKARTA SELATAN",
  "province_code": "31",
  "province": "DKI JAKARTA",
  "postal_codes": ["12210"],
  "is_courier_support": true
}

Yang kamu ambil dari sini adalah code, karena itulah yang dikirim ke cek ongkir nanti. Halaman /villages selalu berisi 100 item dan ukurannya tidak bisa kamu atur, jadi kalau namanya umum, persempit pencarian atau pakai hierarki kecamatan. Untuk contoh yang kita ikuti sampai akhir artikel, kelurahan gudang di Pademangan, Jakarta Utara punya code 3172051003, dan kelurahan tujuan di Rancabali, Kabupaten Bandung punya code 3204402005.

Cek is_courier_support sebelum lanjut

Perhatikan field is_courier_support di respons tadi. Field ini menandai apakah kelurahan itu sudah masuk cakupan kurir. Kamu cek nilainya sebelum memanggil cek ongkir: kalau salah satu kelurahan bernilai false, Expedition akan menolak rute itu dengan galat “not supported”. Dengan memeriksanya lebih dulu, kamu bisa menampilkan pesan yang jelas ke pembeli (“wilayah ini belum didukung”) tanpa memakai kuota untuk panggilan yang sudah pasti gagal.

Memanggil /expedition/shipping-cost

Begitu kamu pegang dua kode kelurahan dan berat paket, tinggal satu panggilan untuk dapat semua tarif. Alamat asal masuk ke origin_village_code, alamat tujuan ke destination_village_code, dan berat dalam kilogram ke weight. Alur lengkapnya dari alamat sampai daftar tarif terlihat seperti ini:

Diagram alur alamat pembeli menuju API Wilayah lalu endpoint tarif kurir
GET https://use.api.co.id/expedition/shipping-cost?origin_village_code=3172051003&destination_village_code=3204402005&weight=1
x-api-co-id: YOUR_API_KEY

Respons membungkus hasilnya dalam envelope is_success, message, dan data, dengan daftar kurir ada di data.couriers. Untuk paket 1 kg dari Pademangan ke Rancabali, balasannya berisi delapan kurir:

{
  "is_success": true,
  "message": "success",
  "data": {
    "origin_village_code": "3172051003",
    "destination_village_code": "3204402005",
    "weight": 1,
    "couriers": [
      { "courier_code": "JNE", "courier_name": "JNE Express", "price": 8000, "weight": 1, "estimation": "2 - 3 days" },
      { "courier_code": "JNE_CARGO", "courier_name": "JNE Cargo", "price": 55000, "weight": 1, "estimation": "2 - 3 days" },
      { "courier_code": "SAP", "courier_name": "SAP Express", "price": 12000, "weight": 1, "estimation": "3 - 5 days" },
      { "courier_code": "SAP_LITE", "courier_name": "SAP Lite", "price": 12000, "weight": 1, "estimation": "3 - 5 days" },
      { "courier_code": "SAP_CARGO", "courier_name": "SAP Cargo", "price": 45000, "weight": 1, "estimation": "3 - 5 days" },
      { "courier_code": "JNT", "courier_name": "J&T Express", "price": 13000, "weight": 1, "estimation": null },
      { "courier_code": "LION", "courier_name": "Lion Parcel", "price": 62330, "weight": 1, "estimation": "4 - 6 Hari" },
      { "courier_code": "NINJA", "courier_name": "Ninja Express", "price": 23000, "weight": 1, "estimation": null }
    ]
  }
}

Yang kamu simpan dari tiap elemen adalah courier_name, price, dan estimation untuk ditampilkan ke pembeli, plus courier_code kalau kamu mau menandai kurir pilihan secara program. Panggilan ulang untuk rute dan berat yang sama dilayani dari cache, jadi gudang yang sering kirim ke tujuan yang itu-itu juga tidak terus memotong kuota.

Membaca array couriers

Dua hal yang perlu kamu jaga saat menampilkan daftar ini. Pertama, hanya kurir dengan price di atas 0 yang dikembalikan, jadi daftar untuk satu rute kadang pendek, dan itu wajar. Kedua, estimation bisa bernilai null dan formatnya campur: satu kurir menulis "2 - 3 days", yang lain "4 - 6 Hari". Tampilkan apa adanya sebagai teks, dan siapkan teks pengganti untuk yang null. Kalau kamu ingin paham kenapa angka estimasi ini bisa meleset dari pengiriman nyata, ada bahasannya di estimasi pengiriman. Rute contoh ini mengembalikan delapan kurir, dari total 14 ekspedisi yang didukung; untuk gambaran lengkapnya lihat daftar ekspedisi yang didukung.

Galat yang muncul dan cara menanganinya

Ada empat galat yang mungkin kamu temui, tiga di antaranya berhubungan dengan parameter yang kamu kirim:

Status Pesan Penyebab Yang kamu lakukan
400 origin_village_code is required / destination_village_code is required parameter kode kelurahan kosong isi kedua kode kelurahan dari API Wilayah
400 Invalid weight parameter weight bukan angka kirim weight sebagai angka kilogram
404 Origin village code '9999999999' does not exist. Please find valid village codes at https://api.co.id/indonesia-regional-api/ kode kelurahan tidak ada ambil kode valid lewat /villages (versi Destination ... untuk tujuan)
400 This village was not supported yet, please open ticket to activate this village kelurahan belum masuk cakupan kurir buka tiket untuk aktivasi; cek is_courier_support lebih dulu

Soal berat, ada satu perilaku yang perlu kamu tahu supaya tidak bingung. Nilai weight di bawah 1 dibulatkan jadi 1 kg sebelum dihitung, jadi paket 0,3 kg tetap dihitung sebagai 1 kg dan tetap menghasilkan tarif. Galat berat baru muncul kalau nilainya memang bukan angka, dan pesannya Invalid weight parameter. Jadi kamu tidak perlu takut panggilan gagal hanya karena berat kecil; yang penting field-nya terisi angka.

Harga, kuota, dan cache

Alur ini memakai dua langganan, dan keduanya model subscription per bulan. Expedition memberi 50 hit gratis untuk kamu coba, API Wilayah tidak. Begini perbandingan paketnya:

Produk Kuota gratis Starter Pro Business
Expedition 50 hit Rp50.000 / 10.000 hit Rp79.000 / 25.000 hit Rp199.000 / 100.000 hit
API Wilayah 0 hit Rp19.000 / 5.000 hit Rp49.000 / 25.000 hit Rp99.000 / 100.000 hit

Cache rute membantu menekan pemakaian kuota Expedition. Respons untuk kombinasi rute dan berat yang sama disimpan, lalu panggilan berikutnya dilayani dari cache. Untuk toko dengan satu gudang tetap, banyak permintaan dari pembeli berbeda yang menuju kelurahan yang sama akan terlayani tanpa menambah hit baru.

Contoh utuh dan kasus checkout

Mari kita satukan semuanya dengan satu paket: 1 kg dari Pademangan (3172051003) ke Rancabali (3204402005). Versi cURL-nya:

curl -s -G 'https://use.api.co.id/expedition/shipping-cost' \
  -H 'x-api-co-id: YOUR_API_KEY' \
  -d origin_village_code=3172051003 \
  -d destination_village_code=3204402005 \
  -d weight=1

Di backend toko, kamu biasanya memanggil ini lalu memetakan hasilnya ke pilihan di checkout. Versi PHP di bawah memakai nilai yang sama, lalu membaca daftar kurirnya:

<?php
$query = http_build_query([
    'origin_village_code' => '3172051003',
    'destination_village_code' => '3204402005',
    'weight' => 1,
]);

$ch = curl_init("https://use.api.co.id/expedition/shipping-cost?$query");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-api-co-id: YOUR_API_KEY']);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);

foreach ($response['data']['couriers'] as $courier) {
    $estimation = $courier['estimation'] ?? 'estimasi menyusul';
    printf("%s - Rp%s (%s)\n",
        $courier['courier_name'],
        number_format($courier['price'], 0, ',', '.'),
        $estimation);
}

Yang perlu kamu jaga di loop itu adalah estimation yang bisa null, jadi jangan langsung mencetaknya tanpa nilai pengganti. Di luar itu, kamu tinggal mengurutkan daftar sesuai selera, misalnya dari harga termurah, sebelum menampilkannya.

Begini wujudnya di toko WooCommerce. Pembeli mengisi alamat lewat dropdown provinsi, kota, kecamatan, sampai kelurahan yang diisi dari API Wilayah, jadi tokomu langsung memegang destination_village_code. Sementara origin_village_code adalah kelurahan gudang yang tetap. Saat pembeli menekan “Cek Ongkir”, backend memanggil /expedition/shipping-cost dengan berat total keranjang, menampilkan JNE, J&T, SiCepat, dan lainnya beserta harga, lalu tarif yang dipilih pembeli masuk ke total pesanan. Kalau kamu menimbang memakai plugin jadi atau membangun endpoint sendiri, pertimbangannya ada di plugin atau custom API.

Langkah berikutnya

Dengan dua panggilan ini kamu sudah punya inti cek ongkir multi-kurir: resolusi alamat jadi kode kelurahan, lalu tarif banyak kurir dalam satu respons. Yang tersisa adalah menempelkannya ke halaman checkout dan menyimpan pilihan pembeli ke pesanan. Pola pemasangannya di website, termasuk kapan memanggil ulang saat keranjang berubah, dibahas di integrasi cek ongkir ke website. Untuk skema endpoint yang lebih rinci, rujukan resminya ada di dokumentasi Expedition.

Pertanyaan yang sering muncul

Apakah layanan cargo ikut muncul di hasil?

Ya. Layanan cargo seperti JNE Cargo dan SAP Cargo muncul sebagai item tersendiri di data.couriers dengan harganya masing-masing, jadi pembeli yang mengirim barang berat bisa langsung memilihnya di daftar yang sama. Kamu tidak memanggil endpoint berbeda untuk cargo.

Bagaimana kalau saya cuma pegang kode pos pembeli?

Kode pos belum cukup karena cek ongkir butuh kode kelurahan 10 digit. Cocokkan dulu kode pos ke kelurahan lewat pencarian di API Wilayah, misalnya dengan parameter postal_code di /villages atau lewat /autocomplete, baru ambil code-nya. Satu kode pos kadang mencakup beberapa kelurahan, jadi tampilkan pilihan ke pembeli bila lebih dari satu; latar belakangnya ada di data kode pos Indonesia.

Ditulis oleh

Rifaldy Elninoru

Founder Api.co.id dan Principal Engineer di PT Akselerasi Platform Indonesia. Membangun platform API serbaguna untuk developer dan perusahaan di Indonesia, mulai dari OCR, data regional, sampai validasi rekening bank. Founding Engineer Lumen Trade di Gotrade (YC S19), merancang mesin trading futures real time berikut integrasi MT4, MT5, dan protokol FIX. Sebelumnya Backend Engineer di Bank Rakyat Indonesia menggarap sistem Ceria dengan Go dan Node.js, serta Web Developer di Direktorat Jenderal Pendidikan Tinggi Kemdikbudristek.

Lihat semua artikel →
Ditinjau oleh

Roni Eka SetiawanExpert Reviewer

CTO Api.co.id. Menangani arsitektur produk, infrastruktur, penetapan harga, dan pengalaman developer untuk API verifikasi identitas, OCR, data keuangan, logistik, geolokasi, data regional, dan AI. Sebelumnya tiga tahun sebagai Web Platform Engineer di Bank Rakyat Indonesia, membangun API pencairan dana real time dengan Go, PostgreSQL, dan Kafka, serta modul KYC, QRIS, dan alur persetujuan pelunasan. Pernah menangani deteksi fraud dan integrasi payment gateway di Airpaz, dan live streaming latensi rendah di Kompas Gramedia. Alumni Bangkit Academy jalur Cloud Computing.

Lihat konten yang ditinjau →
Scroll to Top