Langsung ke konten

Cari

    Menu dokumentasi

    API Reference

    Tarif

    Cek ongkir yang bisa dipesan.

    Cek tarif

    POST 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

    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 body permintaan
    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: PICKUPDROP

    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

    • 200 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
      id string, wajib

      ID penawaran (quoteId). Berlaku 30 menit.

      livemode boolean, wajib

      False untuk kunci test.

      pickupType string, wajib

      -

      Nilai: PICKUPDROP

      insured boolean, wajib

      Penawaran dengan asuransi.

      expiresAt string (date-time), wajib

      Batas penawaran bisa dipakai.

      rates array<Rate>, wajib

      Layanan 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
          }
        ]
      }
    • 400 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"
        }
      }
    • 401 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"
        }
      }
    • 403 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"
          }
        }
      }
    • 409 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"
        }
      }
    • 413 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
          }
        }
      }
    • 415 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"
        }
      }
    • 422 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"
        }
      }
    • 429 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
          }
        }
      }
    • 500 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"
        }
      }
    • 503 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"
        }
      }
    • 504 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 objek 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 objek Location
    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 objek LatLng
    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 objek 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 objek 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: REGULARORGANICLIQUIDELECTRONIC

    bawaan "REGULAR"

    Dimensions

    Field objek 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 objek Rate
    Field Keterangan
    rateCode string, wajib

    Kode layanan, dipakai saat membuat pengiriman.

    courierCode string | null, wajib

    Kode kurir.

    Nilai: jnejntjtcsicepatspxlionpospaxelgosendanteraja

    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 objek Etd
    Field Keterangan
    min integer, wajib

    Estimasi tercepat.

    max integer, wajib

    Estimasi terlama.

    unit string, wajib

    -

    Nilai: DAYHOURMINUTE

    PriceBreakdown

    Field objek 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 objek 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.