Dynamic Indonesian shipping depends on two separate contracts: the host resolves a customer address to provider-compatible region metadata, then a quote provider prices the complete parcel. Keep those boundaries explicit so region data can change without rewriting the commerce core.
Import region data
@adocommercekit/id does not bundle Indonesian administrative-region rows. The host must obtain and maintain a source whose distribution and update terms it has reviewed.
pnpm add @adocommercekit/id
node ace configure @adocommercekit/id
node ace migration:run
node ace commerce:id:regions-import --file ./data/indonesia-regions.jsonKeep the source file, license decision, retrieval date, checksum, and import result in the merchant’s controlled release evidence. Re-import through the command rather than editing region tables manually.
The configure hook publishes reviewable host-owned validator, controller, and route stubs. Before exposing typeahead or validation routes, add host authorization where needed, bound input length, rate-limit search, and return only the fields the checkout needs.
Address rules
Use validateIndonesiaAddress() only for countryCode: "ID". Preserve the selected region identifiers in address metadata so the quote driver does not have to infer locations from display text.
A production checkout should collect:
- recipient name and a normalized Indonesian phone number;
- street and building detail;
- province, kabupaten/kota, kecamatan, and postal code at the precision required by the provider;
- provider destination identifiers under stable host metadata; and
- delivery notes separately from the canonical address.
Never accept a browser-provided shipping price. The server must request a quote from the stored address and parcel, sign the selected quote, and verify that selection during checkout.
Biteship: rates and fulfillment
pnpm add @adocommercekit/biteship
node ace configure @adocommercekit/biteshipimport { biteship } from "@adocommercekit/biteship"
const biteshipDriver = biteship({
apiKey: env.get("COMMERCE_BITESHIP_API_KEY"),
origin: {
areaId: env.get("COMMERCE_BITESHIP_ORIGIN_AREA_ID"),
address: "Warehouse address",
contactName: "Operations",
contactPhone: "+6281234567890",
},
couriers: ["jne", "jnt", "sicepat"],
})
shipping: {
quoteProviders: { biteship: biteshipDriver },
},
fulfillment: {
providers: { biteship: biteshipDriver },
}Biteship includes parcel value, weight, dimensions, destination, COD, insurance, currency, and provider options in quote/cache identity. Rates require IDR and an Indonesian destination. Shipment preparation requires a selected courier:service; tracking webhooks must fail closed until the host supplies a verifier matching its pinned provider contract.
RajaOngkir: rates and available tracking
pnpm add @adocommercekit/rajaongkir
node ace configure @adocommercekit/rajaongkirimport { rajaOngkir } from "@adocommercekit/rajaongkir"
shipping: {
quoteProviders: {
rajaongkir: rajaOngkir({
apiKey: env.get("COMMERCE_RAJAONGKIR_API_KEY"),
originId: env.get("COMMERCE_RAJAONGKIR_ORIGIN_ID"),
couriers: ["jne", "jnt", "sicepat"],
}),
},
}Destinations need rajaOngkirDestinationId metadata—directly or under metadata.indonesia—or a host resolveDestination callback. Rates require IDR, an Indonesian address, and positive aggregate parcel weight.
RajaOngkir explicitly reports waybill creation, fulfillment, COD, and insurance as unsupported. Do not emulate those capabilities. Pair it with a separate fulfillment process only when the host can represent that boundary honestly.
Operational checklist
- Confirm every sellable variant has weight and any dimensions required by enabled couriers.
- Verify origin IDs and courier codes in the provider environment used by the merchant.
- Cache quotes for no longer than the provider allows; Biteship caps the rate-cache TTL at 60 seconds.
- Expire signed selections when address, parcel, currency, provider options, or cart contents change.
- Reconcile shipment state transitions and webhook retries against the host order timeline.
- Keep API keys, raw addresses, recipient phone numbers, and full provider payloads out of logs.
Continue
- Configure payments for Indonesia.
- Review IDR and PPN evidence.
- Learn how generic state machines and workflows protect fulfillment transitions.
- Use the operations guide before enabling webhooks and queues.