Skip to content

Create booking / Get quote

POST /api/bookings/v4

Creates a new booking and returns quotes from all available couriers. The booking is created with a new status and can be confirmed later with a selected courier and pickup date.

This endpoint serves as both a quote request and the first step in the booking lifecycle.

FieldTypeRequiredDescription
declared_valuestringNoDeclared value of the goods in AUD (e.g. "1000.00"). Used for insurance calculations. See warranty and insurance.
include_warrantybooleanNoSet to false to opt out of warranty/insurance on this quote. Defaults to true. See warranty and insurance.
referrerstringNoIdentifies the source of the booking (e.g. "API", "WooCommerce").
requesting_sitestringNoURL of the site making the request (e.g. "http://www.example.com").
tailgate_pickupbooleanNoWhether a tailgate (tail lift) is required at pickup. Defaults to false.
tailgate_deliverybooleanNoWhether a tailgate (tail lift) is required at delivery. Defaults to false.
itemsarrayYesArray of item objects. At least one item is required.
senderobjectYesSender location details.
receiverobjectYesReceiver location details.
payment_methodstringNoWhen supplied, the booking is created and confirmed in a single call (see book with payment). One of: nab_<id> / paypal_<id> (a saved method from GET /api/members/payment-methods), or "demo" for a sandbox booking. Requires courier and pickup_date to also be present. Omit this field to create a quote-only booking and confirm it later.
courierstringConditionalRequired when payment_method is set. Courier identifier to book (e.g. "allied"). Ignored for payment_method: "demo" (the Demo courier is always used).
pickup_datestringConditionalRequired when payment_method is set. Desired pickup date in YYYY-MM-DD format.
pickup_timestringNoOptional pickup time window when booking with payment_method.

The minimum fields required at quote time are postcode, suburb, type, and country. You can include the full address fields below at create time, or add them later via update booking before confirming.

FieldTypeRequiredDescription
postcodestringYesPostcode of the location (e.g. "2000").
suburbstringYesSuburb name in uppercase (e.g. "SYDNEY").
typestringYesAddress type: "business" or "residential".
countrystringNoISO 3166-1 alpha-2 country code. Defaults to "AU". Use "US", "SG", etc. for international shipments.
statestringNoState or territory abbreviation (e.g. "NSW", "VIC"). Auto-derived from postcode if omitted.
namestringNoContact name.
company_namestringNoCompany or business name.
emailstringNoContact email address.
phonestringNoContact phone number.
addressstringNoStreet address.
FieldTypeRequiredDescription
weightstringYesWeight in kilograms (e.g. "5").
heightstringYesHeight in centimetres (e.g. "25").
widthstringYesWidth in centimetres (e.g. "35").
lengthstringYesLength in centimetres (e.g. "40").
quantityintegerYesNumber of identical items.
descriptionstringYesPackaging type from the allowed list (e.g. "Carton", "Satchel", "Pallet") — not free-text product names. See items and packaging.
skustringNoOptional SKU. Echoed in the create response only — not persisted. Subsequent GET /bookings/v4/{id} calls will not return it. Useful when consumers want to correlate input items with the response item order.
Terminal window
curl -X POST \
-H "Api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"declared_value": "1000.00",
"referrer": "API",
"requesting_site": "http://www.example.com",
"tailgate_pickup": false,
"tailgate_delivery": false,
"items": [
{
"weight": "5",
"height": "25",
"width": "35",
"length": "40",
"quantity": 1,
"description": "carton"
}
],
"sender": {
"postcode": "2000",
"suburb": "SYDNEY",
"type": "business",
"country": "AU"
},
"receiver": {
"postcode": "3000",
"suburb": "MELBOURNE",
"type": "business",
"country": "AU"
}
}' \
https://www.transdirect.com.au/api/bookings/v4
{
"id": 12345678,
"status": "new",
"items": [
{
"weight": 5,
"height": 25,
"width": 35,
"length": 40,
"quantity": 1,
"description": "carton"
}
],
"sender": {
"postcode": "2000",
"suburb": "SYDNEY",
"type": "business",
"country": "AU"
},
"receiver": {
"postcode": "3000",
"suburb": "MELBOURNE",
"type": "business",
"country": "AU"
},
"quotes": {
"allied": {
"total": 79.24,
"price_insurance_ex": 72.09,
"fee": 7.15,
"insured_amount": 4500,
"service": "road",
"transit_time": "1-2 days",
"pickup_dates": ["2025-08-27", "2025-08-28"],
"pickup_time": {
"from": "14:00",
"to": "18:00"
}
},
"couriers_please": {
"total": 11.03,
"price_insurance_ex": 10.03,
"fee": 1.00,
"insured_amount": 1000,
"service": "road",
"transit_time": "2-4 days",
"pickup_dates": ["2025-08-27", "2025-08-28", "2025-08-29"],
"pickup_time": {
"from": "08:00",
"to": "18:00"
}
},
"tnt_road_express": {
"total": 45.67,
"price_insurance_ex": 41.52,
"fee": 4.15,
"insured_amount": 3000,
"service": "road",
"transit_time": "1-3 days",
"pickup_dates": ["2025-08-27", "2025-08-28"],
"pickup_time": {
"from": "09:00",
"to": "17:00"
}
}
}
}

Each courier quote object contains:

FieldTypeDescription
totalnumberFinal price including warranty fee (AUD, GST-inclusive).
price_insurance_exnumberCarrier price excluding the warranty/insurance fee (AUD, GST-inclusive).
feenumberWarranty fee component (AUD). See warranty and insurance.
applied_gstnumberGST component of price_insurance_ex, calculated as price_insurance_ex / 11 rounded to 2 decimals. GST is computed on the carrier price only, not on the warranty fee.
insured_amountnumberInsured value (AUD). Equal to declared_value unless capped by the courier’s maximum — see warranty and insurance.
servicestringService type (e.g. "road", "air").
transit_timestringEstimated delivery timeframe (e.g. "1 Business Day", "2-5 Business Days").
pickup_datesarrayAvailable pickup dates in YYYY-MM-DD format.
pickup_timeobjectPickup time window with from and to fields in HH:MM format.
rate_card_codestringRate-card code for the quote (may be empty). Useful when raising support questions about pricing.
tiersarrayOptional. Frequent-rate (multipickup) pricing tiers, returned for Aramex and Couriers Please when frequent rates apply. See frequent rates for shape.

In addition to the keyed quotes object, the response includes a top-level quote_errors array listing couriers that could not provide a quote (e.g. [{"courier": "direct_couriers_express", "code": "no_service", "serviceability": "route.not_serviced", "retryable": false}, ...]).

Check it before treating quotes as the whole market. Any serviceability outside the route/items/service absences means a carrier that should have priced did not, so a cheaper rate may be missing from the list — note that most of those carry retryable: false, so retryable is not the test for completeness. See not every carrier answers.

Every quote includes warranty/insurance coverage based on declared_value. The fee and coverage cap vary by courier.

Each courier sets its own rules:

  • Some couriers include free coverage up to a per-courier cap. For these, fee is 0 and insured_amount is the lower of your declared_value and the cap.
  • Other couriers charge a tiered warranty fee based on the declared_value bracket, up to a per-courier maximum coverage. If declared_value exceeds the cap, insured_amount is returned at the capped value (not your declared value).

The exact fees and caps differ by courier and may change over time. Treat the values returned in fee, insured_amount, and total as authoritative — do not hardcode warranty pricing in your integration.

Send include_warranty: false in the request body to receive quotes without warranty. Every courier in the response will return fee: 0 and insured_amount: 0.

include_warranty: false takes precedence over declared_value — even if you send a non-zero declared_value, no warranty will be added when include_warranty is false. It also bypasses any API-key-level auto-insurance setting that would otherwise top up a zero declared value.

  • fee and insured_amount are courier-specific. Read them from each quote object — don’t assume parity across carriers.
  • Compare total, not price_insurance_ex. Two carriers with the same headline price will have different totals once warranty is included.
  • GST is on price_insurance_ex only. applied_gst = round(price_insurance_ex / 11, 2). The warranty fee is not GST-bearing in the quote response.
  • After confirmation, the booking response replaces quotes with cost and insured_value reflecting the selected courier’s coverage.

By default this endpoint creates a quote-only booking (status: "new") that you confirm later. If you already know the courier and pickup date, you can create and confirm a live booking in one call by including payment_method, courier, and pickup_date:

Terminal window
curl -X POST \
-H "Api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"payment_method": "nab_123",
"courier": "allied",
"pickup_date": "2025-08-18",
"items": [ { "weight": "5", "height": "25", "width": "35", "length": "40", "quantity": 1, "description": "carton" } ],
"sender": { "postcode": "2000", "suburb": "SYDNEY", "type": "business", "country": "AU", "name": "Jane", "phone": "0400000000", "address": "1 George St" },
"receiver": { "postcode": "3000", "suburb": "MELBOURNE", "type": "business", "country": "AU", "name": "John", "phone": "0400000001", "address": "2 Collins St" }
}' \
https://www.transdirect.com.au/api/bookings/v4

payment_method accepts:

ValueEffect
nab_<id>Charge a saved NAB credit card. The <id> comes from GET /api/members/payment-methods.
"credit"Bill your Transdirect credit account. Requires courier and pickup_date, and confirms the booking in the same call.
paypal_<id>Charge a saved PayPal billing agreement.
"demo"Create a demo booking — no charge, not sent to a courier.

If you omit payment_method, the booking is created as a quote. When you later confirm it, the cost is billed to your credit account by default (if you have one with available credit) — or to a saved card or PayPal agreement if you pass payment_method (or payment) on the confirm request.

API access is open by default — no approval step. A live booking simply requires the ability to pay:

Status codeMeaning
402A supplied saved payment method was declined. The response includes a payment_error object (code, user_message, method, log_id).
403No payment capability (no credit account and no saved payment method), the credit limit has been reached, or API access has been disabled for the account. The response includes an access_error object with code (NO_PAYMENT_METHOD, CREDIT_LIMIT_REACHED or API_ACCESS_DISABLED) and a user_message. To make live bookings, add a saved payment method or set up a credit account — or use payment_method: "demo" to test without paying.

Set payment_method: "demo" to confirm the booking as a sandbox booking:

  • It is placed on the synthetic Demo courier and receives a DEMO-XXXXXXXX connote.
  • No charge is made and it is never transmitted to a real courier.
  • The label endpoint returns a watermarked test label.
Terminal window
curl -X POST \
-H "Api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"payment_method": "demo",
"pickup_date": "2025-08-18",
"items": [ { "weight": "5", "height": "25", "width": "35", "length": "40", "quantity": 1, "description": "carton" } ],
"sender": { "postcode": "2000", "suburb": "SYDNEY", "type": "business", "country": "AU", "name": "Jane", "phone": "0400000000", "address": "1 George St" },
"receiver": { "postcode": "3000", "suburb": "MELBOURNE", "type": "business", "country": "AU", "name": "John", "phone": "0400000001", "address": "2 Collins St" }
}' \
https://www.transdirect.com.au/api/bookings/v4

You do not need a courier for a demo booking — the Demo courier is always used.

For international shipments, set the country field on the sender or receiver to the appropriate ISO 3166-1 alpha-2 code (e.g. "US", "SG", "NZ"). If omitted, the country defaults to "AU".

International bookings may require a customs declaration before the booking can be confirmed.