Langsung ke konten

Cari

    Menu dokumentasi

    API Reference

    Pengiriman

    Buat, lihat, dan batalkan pengiriman.

    Daftar pengiriman

    GET https://api.ongkirhub.com/v1/shipments

    Pengiriman di mode kunci ini, terbaru dulu.

    Akses (scope): shipments:read.

    Butuh kunci API (bearerAuth)

    Parameter query

    Parameter query
    Field Keterangan
    status string

    Satu atau beberapa status, dipisah koma.

    awb string

    Nomor resi.

    externalRef string

    Referensi milikmu.

    createdFrom string (date-time)

    Dibuat sejak (inklusif), ISO 8601.

    createdTo string (date-time)

    Dibuat sebelum (eksklusif), ISO 8601.

    limit integer

    Jumlah data per halaman.

    cursor string

    nextCursor dari halaman sebelumnya.

    Contoh permintaan

    curl -X GET "https://api.ongkirhub.com/v1/shipments" \
      -H "Authorization: Bearer ohk_test_xxx"

    Respons

    • 200 Satu halaman pengiriman.
      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.
      Field respons 200
      Field Keterangan
      data array<Shipment>, wajib

      -

      hasMore boolean, wajib

      Masih ada data setelah halaman ini.

      nextCursor string | null, wajib

      Kirim sebagai parameter cursor untuk halaman berikutnya. Null di halaman terakhir.

      {
        "data": [
          {
            "id": "OH0HZ3K7Q2M4XB",
            "livemode": true,
            "status": "awb_ready",
            "statusLabel": "Resi terbit",
            "stage": "manifested",
            "courier": {
              "code": "jne",
              "name": "JNE"
            },
            "service": {
              "rateCode": "REG23",
              "name": "Reguler",
              "etd": {
                "min": 1,
                "max": 2,
                "unit": "DAY"
              }
            },
            "awb": "CGK0123456789012",
            "shipper": {
              "name": "Toko Contoh Jaya",
              "phone": "6281200000001",
              "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"
              },
              "latlng": null
            },
            "receiver": {
              "name": "Dimas Pratama",
              "phone": "6281300000102",
              "email": null,
              "address": "Jl. Penerima No. 2, dekat masjid, Lebak Gede",
              "location": {
                "province": "Jawa Barat",
                "city": "Bandung",
                "district": "Coblong",
                "subdistrict": "Lebak Gede",
                "zipcode": "40132"
              },
              "latlng": null
            },
            "items": [
              {
                "name": "Kaos katun",
                "sku": "KAOS-HITAM-L",
                "qty": 2,
                "weightKg": 0.5,
                "value": 85000,
                "dimensions": {
                  "lengthCm": 25,
                  "widthCm": 20,
                  "heightCm": 5
                },
                "itemType": "REGULAR"
              }
            ],
            "parcel": {
              "weightKg": 1,
              "chargeableWeightKg": 1,
              "declaredValue": 170000
            },
            "insurance": {
              "insured": false,
              "price": 0
            },
            "pricing": {
              "courierPrice": 12000,
              "insurancePrice": 0,
              "serviceFee": 0,
              "total": 12000
            },
            "pickup": {
              "type": "DROP",
              "time": null
            },
            "tracking": {
              "lastCheckedAt": "2026-10-11T04:10:00.000Z",
              "origin": "JAKARTA",
              "destination": "BANDUNG",
              "courierStatus": "MANIFESTED",
              "events": [
                {
                  "at": "2026-10-11T04:05:00.000Z",
                  "rawDate": "2026-10-11 11:05:00",
                  "description": "SHIPMENT RECEIVED BY JNE COUNTER OFFICER AT [JAKARTA]"
                }
              ]
            },
            "timeline": [
              {
                "status": "submitting",
                "label": "Sedang diproses",
                "at": "2026-10-11T03:01:00.000Z",
                "note": null
              },
              {
                "status": "booked",
                "label": "Menunggu resi",
                "at": "2026-10-11T03:01:04.000Z",
                "note": null
              },
              {
                "status": "awb_ready",
                "label": "Resi terbit",
                "at": "2026-10-11T03:02:10.000Z",
                "note": null
              }
            ],
            "error": null,
            "externalRef": "INV-2026-10-0412",
            "notes": null,
            "payment": null,
            "source": "api",
            "createdAt": "2026-10-11T03:01:00.000Z",
            "updatedAt": "2026-10-11T04:10:00.000Z",
            "bookedAt": "2026-10-11T03:01:04.000Z",
            "deliveredAt": null
          }
        ],
        "hasMore": false,
        "nextCursor": 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"
          }
        }
      }
    • 422 Isi permintaan belum 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": "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"
              }
            ]
          }
        }
      }
    • 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"
        }
      }

    Buat pengiriman

    POST https://api.ongkirhub.com/v1/shipments

    Pesan layanan dari penawaran. Total harga ditahan dari saldo (mode test: saldo uji) dan pengiriman langsung dikembalikan dengan status submitting; pesanan diteruskan ke kurir beberapa detik kemudian. Satu penawaran hanya bisa dipakai untuk satu pengiriman, kecuali pengiriman sebelumnya gagal.

    Akses (scope): shipments:write.

    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

    quoteId string, wajib

    id dari respons POST /v1/rates.

    rateCode string, wajib

    rateCode layanan yang dipilih.

    pola ^[A-Za-z0-9_-]{1,64}$

    pickupTime string (date-time)

    Wajib untuk PICKUP: startAt salah satu pickupSlots dari rate yang dipilih.

    notes string

    Catatan untuk kurir.

    maks 500 karakter

    externalRef string

    Referensi milikmu, misalnya nomor pesanan toko. Bisa dipakai untuk mencari pengiriman.

    pola ^[A-Za-z0-9._/-]{1,64}$

    Contoh body: Antar ke gerai (DROP)

    {
      "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,
      "quoteId": "6709f1c2a1b2c3d4e5f60718",
      "rateCode": "REG23",
      "externalRef": "INV-2026-10-0412"
    }

    Contoh body: Dijemput kurir (PICKUP)

    {
      "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": "PICKUP",
      "insured": false,
      "quoteId": "6709f1c2a1b2c3d4e5f60719",
      "rateCode": "REG23",
      "pickupTime": "2026-10-12T09:00:00+07:00"
    }

    Contoh permintaan

    curl -X POST "https://api.ongkirhub.com/v1/shipments" \
      -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,
      "quoteId": "6709f1c2a1b2c3d4e5f60718",
      "rateCode": "REG23",
      "externalRef": "INV-2026-10-0412"
    }'

    Respons

    • 201 Pengiriman dibuat dan sedang 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.
      Idempotent-Replayed
      true jika respons ini adalah ulangan respons yang tersimpan untuk Idempotency-Key yang sama.
      Field respons 201
      Field Keterangan
      id string, wajib

      ID pengiriman OngkirHub (OH + 12 karakter).

      pola ^OH[0-9A-HJKMNP-TV-Z]{12}$

      livemode boolean, wajib

      False untuk pengiriman dari kunci test (simulasi, tanpa kurir sungguhan).

      status string, wajib

      Status pengiriman di OngkirHub. quoted hanya dipakai untuk bayar per resi dari aplikasi (menunggu pembayaran), yang saat ini tidak tersedia.

      Nilai: quotedsubmittingbookedawb_readypicked_upin_transitout_for_deliverydeliveredfailedunknownproblemreturnedcancel_requestedcancelledexpired

      statusLabel string, wajib

      Label status dalam Bahasa Indonesia.

      stage string | null, wajib

      Tahap perjalanan dari data pelacakan.

      Nilai: manifestedpicked_upin_transitout_for_deliverydeliveredproblemreturnedcancelledunknown

      courier object, wajib

      -

      courier.code string | null, wajib

      -

      Nilai: jnejntjtcsicepatspxlionpospaxelgosendanteraja

      courier.name string, wajib

      Nama kurir.

      service object, wajib

      -

      service.rateCode string, wajib

      Kode layanan.

      service.name string, wajib

      Nama layanan.

      service.etd Etd | null, wajib

      Estimasi waktu sampai dari kurir.

      awb string | null, wajib

      Nomor resi. Null sampai resi terbit (status awb_ready).

      shipper Party, wajib

      -

      receiver Party, wajib

      -

      items array<ShipmentItem>, wajib

      -

      parcel object, wajib

      -

      parcel.weightKg number, wajib

      Total berat.

      parcel.chargeableWeightKg number | null, wajib

      -

      parcel.declaredValue integer, wajib

      Total nilai barang. Rupiah, bilangan bulat.

      insurance object, wajib

      -

      insurance.insured boolean, wajib

      Diasuransikan.

      insurance.price integer, wajib

      Biaya asuransi. Rupiah, bilangan bulat.

      pricing PriceBreakdown, wajib

      -

      pickup object, wajib

      -

      pickup.type string, wajib

      -

      Nilai: PICKUPDROP

      pickup.time string (date-time) | null, wajib

      Jadwal jemput.

      tracking object, wajib

      -

      tracking.lastCheckedAt string (date-time) | null, wajib

      Terakhir data pelacakan diperbarui.

      tracking.origin string | null, wajib

      Asal menurut kurir.

      tracking.destination string | null, wajib

      Tujuan menurut kurir.

      tracking.courierStatus string | null, wajib

      Status menurut kurir.

      tracking.events array<TrackingEvent>, wajib

      Riwayat dari kurir, terbaru dulu.

      timeline array<object>, wajib

      Riwayat status OngkirHub, terlama dulu.

      timeline[].status string, wajib

      -

      Nilai: quotedsubmittingbookedawb_readypicked_upin_transitout_for_deliverydeliveredfailedunknownproblemreturnedcancel_requestedcancelledexpired

      timeline[].label string, wajib

      Label status.

      timeline[].at string (date-time), wajib

      Waktu perubahan.

      timeline[].note string | null, wajib

      Catatan.

      error object | null, wajib

      -

      error.code string, wajib

      -

      Nilai: invalid_requestmethod_not_allowedpayload_too_largeunsupported_media_typeidempotency_key_reusedvalidation_errorunauthenticatedforbiddennot_foundrate_limitedidempotency_conflictquote_expiredno_rates_availablepickup_time_requiredcoordinates_requiredwallet_insufficient_fundsdaily_limit_reachedamount_limit_exceededbooking_disabledcourier_rejectedcourier_service_unavailableorder_reconcilingservice_unavailableservice_timeouttracking_not_foundtracking_courier_requiredtracking_verification_requiredtracking_unsupported_couriertopup_below_minimumtopup_above_limitpayment_method_unavailablepayment_expiredshipment_payment_expiredshipment_needs_rebookingclaim_not_allowedclaim_already_openupload_invalidcancellation_not_allowedmail_unavailablenetwork_errorinternal_error

      error.message string, wajib

      Penjelasan.

      externalRef string | null, wajib

      Referensi milikmu.

      notes string | null, wajib

      Catatan untuk kurir.

      payment object | null, wajib

      Bayar per resi dari aplikasi. Saat ini tidak tersedia: pengiriman dibayar dari saldo, jadi bernilai null kecuali pada pengiriman lama. Pengiriman dari API selalu dibayar dari saldo.

      payment.method string, wajib

      -

      Nilai: walletgateway

      payment.topupCode string | null, wajib

      Kode pembayaran (TU…) untuk bayar per resi.

      payment.paymentMethod string | null, wajib

      Metode pembayaran.

      payment.expiresAt string (date-time) | null, wajib

      Batas bayar.

      payment.paidAt string (date-time) | null, wajib

      Dibayar.

      source string, wajib

      Dibuat dari aplikasi atau API.

      Nilai: appapi

      createdAt string (date-time), wajib

      Dibuat.

      updatedAt string (date-time), wajib

      Terakhir berubah.

      bookedAt string (date-time) | null, wajib

      Diterima kurir untuk diproses.

      deliveredAt string (date-time) | null, wajib

      Diterima penerima.

      {
        "id": "OH0HZ3K7Q2M4XB",
        "livemode": true,
        "status": "submitting",
        "statusLabel": "Sedang diproses",
        "stage": null,
        "courier": {
          "code": "jne",
          "name": "JNE"
        },
        "service": {
          "rateCode": "REG23",
          "name": "Reguler",
          "etd": {
            "min": 1,
            "max": 2,
            "unit": "DAY"
          }
        },
        "awb": null,
        "shipper": {
          "name": "Toko Contoh Jaya",
          "phone": "6281200000001",
          "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"
          },
          "latlng": null
        },
        "receiver": {
          "name": "Dimas Pratama",
          "phone": "6281300000102",
          "email": null,
          "address": "Jl. Penerima No. 2, dekat masjid, Lebak Gede",
          "location": {
            "province": "Jawa Barat",
            "city": "Bandung",
            "district": "Coblong",
            "subdistrict": "Lebak Gede",
            "zipcode": "40132"
          },
          "latlng": null
        },
        "items": [
          {
            "name": "Kaos katun",
            "sku": "KAOS-HITAM-L",
            "qty": 2,
            "weightKg": 0.5,
            "value": 85000,
            "dimensions": {
              "lengthCm": 25,
              "widthCm": 20,
              "heightCm": 5
            },
            "itemType": "REGULAR"
          }
        ],
        "parcel": {
          "weightKg": 1,
          "chargeableWeightKg": 1,
          "declaredValue": 170000
        },
        "insurance": {
          "insured": false,
          "price": 0
        },
        "pricing": {
          "courierPrice": 12000,
          "insurancePrice": 0,
          "serviceFee": 0,
          "total": 12000
        },
        "pickup": {
          "type": "DROP",
          "time": null
        },
        "tracking": {
          "lastCheckedAt": null,
          "origin": null,
          "destination": null,
          "courierStatus": null,
          "events": []
        },
        "timeline": [
          {
            "status": "submitting",
            "label": "Sedang diproses",
            "at": "2026-10-11T03:01:00.000Z",
            "note": null
          }
        ],
        "error": null,
        "externalRef": "INV-2026-10-0412",
        "notes": null,
        "payment": null,
        "source": "api",
        "createdAt": "2026-10-11T03:01:00.000Z",
        "updatedAt": "2026-10-11T03:01:00.000Z",
        "bookedAt": null,
        "deliveredAt": 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"
        }
      }
    • 402 Saldo tidak cukup.
      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": "wallet_insufficient_funds",
          "message": "Saldo OngkirHub kamu belum cukup untuk pengiriman ini. Isi saldo dulu, lalu coba lagi.",
          "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12",
          "details": {
            "available": 5000,
            "required": 12000
          }
        }
      }
    • 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 Penawaran kedaluwarsa atau harganya berubah, penawaran sudah dipakai, Idempotency-Key sudah dipakai pengiriman lain, atau permintaan 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.

      Penawaran kedaluwarsa

      {
        "error": {
          "code": "quote_expired",
          "message": "Harga ongkir sudah diperbarui. Cek ongkir lagi sebelum membuat resi.",
          "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12"
        }
      }

      Penawaran sudah dipakai

      {
        "error": {
          "code": "idempotency_conflict",
          "message": "Penawaran ini sudah dipakai untuk pengiriman OH0HZ3K7Q2M4XB. Cek tarif lagi untuk membuat pengiriman lain.",
          "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12",
          "details": {
            "shipmentId": "OH0HZ3K7Q2M4XB"
          }
        }
      }

      Idempotency-Key sudah dipakai

      {
        "error": {
          "code": "idempotency_conflict",
          "message": "Idempotency-Key ini sudah dipakai untuk pengiriman lain (isi berbeda atau mode test/live lain). Pakai kunci baru.",
          "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12"
        }
      }

      Permintaan sama masih diproses

      {
        "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, melebihi batas per pengiriman, layanan tidak tersedia, 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": "pickupTime",
                "message": "Pilih jadwal penjemputan"
              }
            ]
          }
        }
      }

      Melebihi batas per pengiriman

      {
        "error": {
          "code": "amount_limit_exceeded",
          "message": "Total biaya melebihi batas per pengiriman untuk akunmu.",
          "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12"
        }
      }

      Layanan kurir tidak tersedia

      {
        "error": {
          "code": "courier_service_unavailable",
          "message": "Layanan kurir ini sedang tidak tersedia. Pilih layanan lain.",
          "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 atau batas pengiriman harian tercapai.
      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.

      Batas permintaan terlampaui

      {
        "error": {
          "code": "rate_limited",
          "message": "Terlalu banyak permintaan. Tunggu sebentar, lalu coba lagi.",
          "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12",
          "details": {
            "retryAfterSec": 21
          }
        }
      }

      Batas harian tercapai

      {
        "error": {
          "code": "daily_limit_reached",
          "message": "Batas pengiriman harian akunmu sudah tercapai. Coba lagi besok atau hubungi kami.",
          "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12"
        }
      }
    • 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"
        }
      }

    Detail pengiriman

    GET https://api.ongkirhub.com/v1/shipments/{id}

    Status, resi, harga, riwayat status, dan data pelacakan terakhir.

    Akses (scope): shipments:read.

    Butuh kunci API (bearerAuth)

    Parameter path

    Parameter path
    Field Keterangan
    id string, wajib

    ID pengiriman (OH…).

    Contoh permintaan

    curl -X GET "https://api.ongkirhub.com/v1/shipments/OH0HZ3K7Q2M4XB" \
      -H "Authorization: Bearer ohk_test_xxx"

    Respons

    • 200 Pengiriman.
      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.
      Field respons 200
      Field Keterangan
      id string, wajib

      ID pengiriman OngkirHub (OH + 12 karakter).

      pola ^OH[0-9A-HJKMNP-TV-Z]{12}$

      livemode boolean, wajib

      False untuk pengiriman dari kunci test (simulasi, tanpa kurir sungguhan).

      status string, wajib

      Status pengiriman di OngkirHub. quoted hanya dipakai untuk bayar per resi dari aplikasi (menunggu pembayaran), yang saat ini tidak tersedia.

      Nilai: quotedsubmittingbookedawb_readypicked_upin_transitout_for_deliverydeliveredfailedunknownproblemreturnedcancel_requestedcancelledexpired

      statusLabel string, wajib

      Label status dalam Bahasa Indonesia.

      stage string | null, wajib

      Tahap perjalanan dari data pelacakan.

      Nilai: manifestedpicked_upin_transitout_for_deliverydeliveredproblemreturnedcancelledunknown

      courier object, wajib

      -

      courier.code string | null, wajib

      -

      Nilai: jnejntjtcsicepatspxlionpospaxelgosendanteraja

      courier.name string, wajib

      Nama kurir.

      service object, wajib

      -

      service.rateCode string, wajib

      Kode layanan.

      service.name string, wajib

      Nama layanan.

      service.etd Etd | null, wajib

      Estimasi waktu sampai dari kurir.

      awb string | null, wajib

      Nomor resi. Null sampai resi terbit (status awb_ready).

      shipper Party, wajib

      -

      receiver Party, wajib

      -

      items array<ShipmentItem>, wajib

      -

      parcel object, wajib

      -

      parcel.weightKg number, wajib

      Total berat.

      parcel.chargeableWeightKg number | null, wajib

      -

      parcel.declaredValue integer, wajib

      Total nilai barang. Rupiah, bilangan bulat.

      insurance object, wajib

      -

      insurance.insured boolean, wajib

      Diasuransikan.

      insurance.price integer, wajib

      Biaya asuransi. Rupiah, bilangan bulat.

      pricing PriceBreakdown, wajib

      -

      pickup object, wajib

      -

      pickup.type string, wajib

      -

      Nilai: PICKUPDROP

      pickup.time string (date-time) | null, wajib

      Jadwal jemput.

      tracking object, wajib

      -

      tracking.lastCheckedAt string (date-time) | null, wajib

      Terakhir data pelacakan diperbarui.

      tracking.origin string | null, wajib

      Asal menurut kurir.

      tracking.destination string | null, wajib

      Tujuan menurut kurir.

      tracking.courierStatus string | null, wajib

      Status menurut kurir.

      tracking.events array<TrackingEvent>, wajib

      Riwayat dari kurir, terbaru dulu.

      timeline array<object>, wajib

      Riwayat status OngkirHub, terlama dulu.

      timeline[].status string, wajib

      -

      Nilai: quotedsubmittingbookedawb_readypicked_upin_transitout_for_deliverydeliveredfailedunknownproblemreturnedcancel_requestedcancelledexpired

      timeline[].label string, wajib

      Label status.

      timeline[].at string (date-time), wajib

      Waktu perubahan.

      timeline[].note string | null, wajib

      Catatan.

      error object | null, wajib

      -

      error.code string, wajib

      -

      Nilai: invalid_requestmethod_not_allowedpayload_too_largeunsupported_media_typeidempotency_key_reusedvalidation_errorunauthenticatedforbiddennot_foundrate_limitedidempotency_conflictquote_expiredno_rates_availablepickup_time_requiredcoordinates_requiredwallet_insufficient_fundsdaily_limit_reachedamount_limit_exceededbooking_disabledcourier_rejectedcourier_service_unavailableorder_reconcilingservice_unavailableservice_timeouttracking_not_foundtracking_courier_requiredtracking_verification_requiredtracking_unsupported_couriertopup_below_minimumtopup_above_limitpayment_method_unavailablepayment_expiredshipment_payment_expiredshipment_needs_rebookingclaim_not_allowedclaim_already_openupload_invalidcancellation_not_allowedmail_unavailablenetwork_errorinternal_error

      error.message string, wajib

      Penjelasan.

      externalRef string | null, wajib

      Referensi milikmu.

      notes string | null, wajib

      Catatan untuk kurir.

      payment object | null, wajib

      Bayar per resi dari aplikasi. Saat ini tidak tersedia: pengiriman dibayar dari saldo, jadi bernilai null kecuali pada pengiriman lama. Pengiriman dari API selalu dibayar dari saldo.

      payment.method string, wajib

      -

      Nilai: walletgateway

      payment.topupCode string | null, wajib

      Kode pembayaran (TU…) untuk bayar per resi.

      payment.paymentMethod string | null, wajib

      Metode pembayaran.

      payment.expiresAt string (date-time) | null, wajib

      Batas bayar.

      payment.paidAt string (date-time) | null, wajib

      Dibayar.

      source string, wajib

      Dibuat dari aplikasi atau API.

      Nilai: appapi

      createdAt string (date-time), wajib

      Dibuat.

      updatedAt string (date-time), wajib

      Terakhir berubah.

      bookedAt string (date-time) | null, wajib

      Diterima kurir untuk diproses.

      deliveredAt string (date-time) | null, wajib

      Diterima penerima.

      {
        "id": "OH0HZ3K7Q2M4XB",
        "livemode": true,
        "status": "awb_ready",
        "statusLabel": "Resi terbit",
        "stage": "manifested",
        "courier": {
          "code": "jne",
          "name": "JNE"
        },
        "service": {
          "rateCode": "REG23",
          "name": "Reguler",
          "etd": {
            "min": 1,
            "max": 2,
            "unit": "DAY"
          }
        },
        "awb": "CGK0123456789012",
        "shipper": {
          "name": "Toko Contoh Jaya",
          "phone": "6281200000001",
          "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"
          },
          "latlng": null
        },
        "receiver": {
          "name": "Dimas Pratama",
          "phone": "6281300000102",
          "email": null,
          "address": "Jl. Penerima No. 2, dekat masjid, Lebak Gede",
          "location": {
            "province": "Jawa Barat",
            "city": "Bandung",
            "district": "Coblong",
            "subdistrict": "Lebak Gede",
            "zipcode": "40132"
          },
          "latlng": null
        },
        "items": [
          {
            "name": "Kaos katun",
            "sku": "KAOS-HITAM-L",
            "qty": 2,
            "weightKg": 0.5,
            "value": 85000,
            "dimensions": {
              "lengthCm": 25,
              "widthCm": 20,
              "heightCm": 5
            },
            "itemType": "REGULAR"
          }
        ],
        "parcel": {
          "weightKg": 1,
          "chargeableWeightKg": 1,
          "declaredValue": 170000
        },
        "insurance": {
          "insured": false,
          "price": 0
        },
        "pricing": {
          "courierPrice": 12000,
          "insurancePrice": 0,
          "serviceFee": 0,
          "total": 12000
        },
        "pickup": {
          "type": "DROP",
          "time": null
        },
        "tracking": {
          "lastCheckedAt": "2026-10-11T04:10:00.000Z",
          "origin": "JAKARTA",
          "destination": "BANDUNG",
          "courierStatus": "MANIFESTED",
          "events": [
            {
              "at": "2026-10-11T04:05:00.000Z",
              "rawDate": "2026-10-11 11:05:00",
              "description": "SHIPMENT RECEIVED BY JNE COUNTER OFFICER AT [JAKARTA]"
            }
          ]
        },
        "timeline": [
          {
            "status": "submitting",
            "label": "Sedang diproses",
            "at": "2026-10-11T03:01:00.000Z",
            "note": null
          },
          {
            "status": "booked",
            "label": "Menunggu resi",
            "at": "2026-10-11T03:01:04.000Z",
            "note": null
          },
          {
            "status": "awb_ready",
            "label": "Resi terbit",
            "at": "2026-10-11T03:02:10.000Z",
            "note": null
          }
        ],
        "error": null,
        "externalRef": "INV-2026-10-0412",
        "notes": null,
        "payment": null,
        "source": "api",
        "createdAt": "2026-10-11T03:01:00.000Z",
        "updatedAt": "2026-10-11T04:10:00.000Z",
        "bookedAt": "2026-10-11T03:01:04.000Z",
        "deliveredAt": null
      }
    • 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"
          }
        }
      }
    • 404 Data tidak ditemukan untuk kunci API 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": "not_found",
          "message": "Pengiriman tidak ditemukan untuk kunci API ini.",
          "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"
        }
      }

    Ajukan pembatalan

    POST https://api.ongkirhub.com/v1/shipments/{id}/cancel

    Ajukan pembatalan untuk pengiriman berstatus booked, awb_ready, atau problem. Mode live: pengiriman berubah menjadi cancel_requested dan tim OngkirHub meninjau permintaan bersama kurir. Jika disetujui, status menjadi cancelled dan saldo dikembalikan (event shipment.cancelled); jika ditolak, status kembali seperti semula. Mode test: permintaan langsung disetujui, respons berstatus refunded dan pengiriman menjadi cancelled.

    Akses (scope): shipments:write.

    Butuh kunci API (bearerAuth)

    Parameter path

    Parameter path
    Field Keterangan
    id string, wajib

    ID pengiriman (OH…).

    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
    reason string, wajib

    Alasan pembatalan.

    min 5 karakter, maks 500 karakter

    Contoh permintaan

    curl -X POST "https://api.ongkirhub.com/v1/shipments/OH0HZ3K7Q2M4XB/cancel" \
      -H "Authorization: Bearer ohk_test_xxx" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: 6f1c2a9e-4b7d-4c1e-9a52-3e8d0b7f1a24" \
      -d '{
      "reason": "Pembeli membatalkan pesanan sebelum paket dijemput"
    }'

    Respons

    • 201 Permintaan pembatalan dibuat (live) atau langsung disetujui (test).
      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 201
      Field Keterangan
      id string, wajib

      ID permintaan pembatalan.

      shipmentId string, wajib

      ID pengiriman (OH…).

      status string, wajib

      requested: menunggu tinjauan tim OngkirHub. refunded: disetujui dan saldo dikembalikan (mode test: langsung, saldo uji). rejected: ditolak.

      Nilai: requestedapprovedrejectedrefunded

      reason string, wajib

      Alasan pembatalan.

      reviewNote string | null, wajib

      Catatan dari tim OngkirHub.

      refundAmount integer | null, wajib

      Saldo yang dikembalikan setelah disetujui.

      createdAt string (date-time), wajib

      Diajukan.

      reviewedAt string (date-time) | null, wajib

      Ditinjau.

      Kunci live: menunggu tinjauan

      {
        "id": "6709f8a0c4d5e6f708192a3b",
        "shipmentId": "OH0HZ3K7Q2M4XB",
        "status": "requested",
        "reason": "Pembeli membatalkan pesanan sebelum paket dijemput",
        "reviewNote": null,
        "refundAmount": null,
        "createdAt": "2026-10-11T05:00:00.000Z",
        "reviewedAt": null
      }

      Kunci test: langsung disetujui

      {
        "id": "6709f8a0c4d5e6f708192a3b",
        "shipmentId": "OH0HZ3K7Q2M4XB",
        "status": "refunded",
        "reason": "Pembeli membatalkan pesanan sebelum paket dijemput",
        "reviewNote": "Disetujui otomatis di mode test",
        "refundAmount": 12000,
        "createdAt": "2026-10-11T05:00:00.000Z",
        "reviewedAt": "2026-10-11T05:00:00.000Z"
      }
    • 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"
          }
        }
      }
    • 404 Data tidak ditemukan untuk kunci API 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": "not_found",
          "message": "Pengiriman tidak ditemukan untuk kunci API ini.",
          "request_id": "req_5f0c2a9e7b1d4c3a8e6f0b12"
        }
      }
    • 409 Pengiriman sudah tidak bisa dibatalkan, atau permintaan 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": "cancellation_not_allowed",
          "message": "Pengiriman ini sudah tidak bisa dibatalkan.",
          "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 permintaan belum 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": "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"
              }
            ]
          }
        }
      }
    • 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"
        }
      }

    Skema objek

    Objek yang dipakai di halaman ini, dijelaskan sekali di sini.

    Shipment

    Field objek Shipment
    Field Keterangan
    id string, wajib

    ID pengiriman OngkirHub (OH + 12 karakter).

    pola ^OH[0-9A-HJKMNP-TV-Z]{12}$

    livemode boolean, wajib

    False untuk pengiriman dari kunci test (simulasi, tanpa kurir sungguhan).

    status string, wajib

    Status pengiriman di OngkirHub. quoted hanya dipakai untuk bayar per resi dari aplikasi (menunggu pembayaran), yang saat ini tidak tersedia.

    Nilai: quotedsubmittingbookedawb_readypicked_upin_transitout_for_deliverydeliveredfailedunknownproblemreturnedcancel_requestedcancelledexpired

    statusLabel string, wajib

    Label status dalam Bahasa Indonesia.

    stage string | null, wajib

    Tahap perjalanan dari data pelacakan.

    Nilai: manifestedpicked_upin_transitout_for_deliverydeliveredproblemreturnedcancelledunknown

    courier object, wajib

    -

    courier.code string | null, wajib

    -

    Nilai: jnejntjtcsicepatspxlionpospaxelgosendanteraja

    courier.name string, wajib

    Nama kurir.

    service object, wajib

    -

    service.rateCode string, wajib

    Kode layanan.

    service.name string, wajib

    Nama layanan.

    service.etd Etd | null, wajib

    Estimasi waktu sampai dari kurir.

    awb string | null, wajib

    Nomor resi. Null sampai resi terbit (status awb_ready).

    shipper Party, wajib

    -

    receiver Party, wajib

    -

    items array<ShipmentItem>, wajib

    -

    parcel object, wajib

    -

    parcel.weightKg number, wajib

    Total berat.

    parcel.chargeableWeightKg number | null, wajib

    -

    parcel.declaredValue integer, wajib

    Total nilai barang. Rupiah, bilangan bulat.

    insurance object, wajib

    -

    insurance.insured boolean, wajib

    Diasuransikan.

    insurance.price integer, wajib

    Biaya asuransi. Rupiah, bilangan bulat.

    pricing PriceBreakdown, wajib

    -

    pickup object, wajib

    -

    pickup.type string, wajib

    -

    Nilai: PICKUPDROP

    pickup.time string (date-time) | null, wajib

    Jadwal jemput.

    tracking object, wajib

    -

    tracking.lastCheckedAt string (date-time) | null, wajib

    Terakhir data pelacakan diperbarui.

    tracking.origin string | null, wajib

    Asal menurut kurir.

    tracking.destination string | null, wajib

    Tujuan menurut kurir.

    tracking.courierStatus string | null, wajib

    Status menurut kurir.

    tracking.events array<TrackingEvent>, wajib

    Riwayat dari kurir, terbaru dulu.

    timeline array<object>, wajib

    Riwayat status OngkirHub, terlama dulu.

    timeline[].status string, wajib

    -

    Nilai: quotedsubmittingbookedawb_readypicked_upin_transitout_for_deliverydeliveredfailedunknownproblemreturnedcancel_requestedcancelledexpired

    timeline[].label string, wajib

    Label status.

    timeline[].at string (date-time), wajib

    Waktu perubahan.

    timeline[].note string | null, wajib

    Catatan.

    error object | null, wajib

    -

    error.code string, wajib

    -

    Nilai: invalid_requestmethod_not_allowedpayload_too_largeunsupported_media_typeidempotency_key_reusedvalidation_errorunauthenticatedforbiddennot_foundrate_limitedidempotency_conflictquote_expiredno_rates_availablepickup_time_requiredcoordinates_requiredwallet_insufficient_fundsdaily_limit_reachedamount_limit_exceededbooking_disabledcourier_rejectedcourier_service_unavailableorder_reconcilingservice_unavailableservice_timeouttracking_not_foundtracking_courier_requiredtracking_verification_requiredtracking_unsupported_couriertopup_below_minimumtopup_above_limitpayment_method_unavailablepayment_expiredshipment_payment_expiredshipment_needs_rebookingclaim_not_allowedclaim_already_openupload_invalidcancellation_not_allowedmail_unavailablenetwork_errorinternal_error

    error.message string, wajib

    Penjelasan.

    externalRef string | null, wajib

    Referensi milikmu.

    notes string | null, wajib

    Catatan untuk kurir.

    payment object | null, wajib

    Bayar per resi dari aplikasi. Saat ini tidak tersedia: pengiriman dibayar dari saldo, jadi bernilai null kecuali pada pengiriman lama. Pengiriman dari API selalu dibayar dari saldo.

    payment.method string, wajib

    -

    Nilai: walletgateway

    payment.topupCode string | null, wajib

    Kode pembayaran (TU…) untuk bayar per resi.

    payment.paymentMethod string | null, wajib

    Metode pembayaran.

    payment.expiresAt string (date-time) | null, wajib

    Batas bayar.

    payment.paidAt string (date-time) | null, wajib

    Dibayar.

    source string, wajib

    Dibuat dari aplikasi atau API.

    Nilai: appapi

    createdAt string (date-time), wajib

    Dibuat.

    updatedAt string (date-time), wajib

    Terakhir berubah.

    bookedAt string (date-time) | null, wajib

    Diterima kurir untuk diproses.

    deliveredAt string (date-time) | null, wajib

    Diterima penerima.

    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

    Party

    Field objek Party
    Field Keterangan
    name string, wajib

    Nama.

    phone string, wajib

    Nomor HP (62…).

    email string | null, wajib

    Email.

    address string, wajib

    Alamat.

    location Location, wajib

    Wilayah tujuan atau asal. Ambil dari GET /v1/locations agar cocok dengan data kurir.

    latlng LatLng | null, wajib

    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

    ShipmentItem

    Field objek ShipmentItem
    Field Keterangan
    name string, wajib

    Nama barang.

    sku string | null, wajib

    SKU.

    qty integer, wajib

    Jumlah.

    weightKg number, wajib

    Berat satu unit dalam kg.

    value integer, wajib

    Nilai satu unit. Rupiah, bilangan bulat.

    dimensions Dimensions | null, wajib

    -

    itemType string, wajib

    -

    Nilai: REGULARORGANICLIQUIDELECTRONIC

    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

    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.

    TrackingEvent

    Field objek TrackingEvent
    Field Keterangan
    at string (date-time) | null, wajib

    Waktu kejadian (UTC). Null jika tanggal dari kurir tidak terbaca.

    rawDate string | null, wajib

    Tanggal seperti yang dikirim kurir.

    description string, wajib

    Keterangan dari kurir.

    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.

    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"